LINUX.ORG.RU

создание дочерних процессов_


0

1

Извиняюсь за предыдущий пост, ночью голова плохо работает. Вот с исправлениями(правда как сделать отступы не знаю: Есть программа которая порождает дочерний процесс и из него передает родительскому привет. Задача стоит в том чтобы изменить код дочернего процесса и сделать его отдельной программой и вызвать через exec. Ниже привожу код с заданием и переработанный мною. Просьба исправить что не так и не сильно пинать, поскольку я никогда не писал на С а тем более под линукс .

Исходный текст


#include "myheader.h"

FILE *stream;

int main() {

 pid_t child_pid;

char filename[] = "/tmp/myprogram.XXXXXX";

int fd;

printf("Parent: The main program's PID is %u\n", (unsigned int) getpid());

/* Создает временный файл. */

fd = mkstemp(filename);

if (fd < 0) 

{ 

fprintf(stderr, "Parent: Can't create temporary file:" " %s\n",strerror(errno));

exit(EXIT_FAILURE);

     }

 stream = fdopen(fd, "r+");

if (stream == NULL) { fprintf(stderr, "Parent: Can't create stream for" " temporary file %s: %s\n", filename, strerror(errno));

exit(EXIT_FAILURE); 

}

if (unlink(filename) < 0) fprintf(stderr, "Parent: Error unlinking temporary file" " %s: %s\n", filename, strerror(errno));

/* Создает дочерний процесс. */

child_pid = fork();

if (child_pid != 0) 

{

/* Это родительсий процесс */

if (child_pid == -1)

 {

/* Ошибка при созд. дочернего процесса. */

fprintf(stderr, "Parent: Error creating a child:" " %s\n",strerror(errno));

exit(EXIT_FAILURE);

} 

exit(parent(child_pid));

 } 

else 
{

 /* Это дочений оцес */ exit(child());

}   

}

------------------------------

/* * parent.c * */

#include "myheader.h"

enum { MSGSIZE = 20 };

extern int parent(pid_t child_pid) {

int child_status;

char message[MSGSIZE];

assert(child_pid > 0);

assert(stream != NULL);

printf("Parent: My PID is %u and my child's PID is %u\n", (unsigned int) getpid(), (unsigned int) child_pid); 

wait(&child_status);

printf("Parent: Child exited with code %d\n", child_status); 

if (fseek(stream, 0, SEEK_SET) != 0)

 { 

fprintf(stderr, "Parent: Error seeking in temporary file:" "%s\n", strerror(errno));

return 1;

}

if (fgets(message, MSGSIZE, stream) == NULL)

 { 

if (ferror(stream)) 

{ fprintf(stderr, "Parent: Error reading from" " temporary file: %s\n", strerror(errno));


 return 1; 

}

printf("Parent: No message from child" " has been received\n");

return 0; 

} 
printf("Parent: A message from child has been received:\n" "%s\n", message);

return 0;   

}

-------------------------------------------------- /* * child.c * */

#include "myheader.h"

extern int child() { assert(stream != NULL);

printf("Child: My PID is %u and my parent's PID is %u\n", (unsigned int) getpid(), (unsigned int) getppid());

if (fputs("Hello, Daddy!", stream) == EOF) 
{ 

fprintf(stderr, "Child: Error writing to temporary file:" " %s\n", strerror(errno));

return 1;

}

return 0;

}

А вот переделанный код. Код parent.c Я оставил без изменений


/* * main2.c * * */

#include "myheader.h"

FILE *stream;

int main() 

{ pid_t child_pid; 

char filename[] ="/tmp/myprogram.XXXXXX"; 

int fd;

printf("Parent: The main program's PID is %u\n", (unsigned int)getpid());

fd = mkstemp(filename);

if (fd < 0) {

fprintf(stderr, "Parent: Can't create temporary file:" " %s\n",strerror(errno));

exit(EXIT_FAILURE);

}

stream = fdopen(fd, "r+");

if (stream == NULL) 

{ fprintf(stderr, "Parent: Can't create stream for" " temporary file %s: %s\n", filename, strerror(errno));

exit(EXIT_FAILURE);

}

if (unlink(filename) < 0) fprintf(stderr, "Parent: Error unlinking temporary file" " %s: %s\n", filename, strerror(errno));

child_pid = fork();

if (child_pid != 0) 

{

 if (child_pid == -1) 

{

 fprintf(stderr, "Parent: Error creating a child:" " %s\n",strerror(errno));

exit(EXIT_FAILURE);

} 

exit(parent(child_pid));

} 

else 

{ 

execl ("/bin/example2", "example2", (char*) 0);

}   

}

----------------------------

/* * child2.c * */

#include "myheader.h"

int main() 

{

pid_t child_pid;

char filename[] = "/tmp/myprogram.XXXXXX";

int fd;


stream = fopen(filename, "r+");

if (stream == NULL) 

{ 

fprintf(stderr, "Child: Can't create stream for" " temporary file%s: %s\n", filename, strerror(errno));

exit(EXIT_FAILURE);

} 

if (unlink(filename) < 0) 

fprintf(stderr, "Child: Error unlinking temporary file" " %s: %s\n",filename, strerror(errno));

printf("Child: My PID is %u and my parent's PID is %u\n", (unsigned int) getpid(), (unsigned int) getppid()); 

if (fputs("Hello, Daddy!",stream) == EOF) 

{

fprintf(stderr, "Child: Error writing to temporary file:" " %s\n",strerror(errno));

}

}

Вас в том (удалёном) топике просили привести исходник программы в читаемом виде. Это когда нет лишних пустых строк и есть отступы, чтобы видеть составные операторы, циклы и т.д.

Если вы не понимате что это, то удалите пустые строки и пропустите ваш фарш через команду indent, можно с опцией -kr.

Если по теме, что в родителе вы создаёте файл, а запущенный через exec() процесс должен знать это имя, допустим через параметр командной строки, а не создавать файл «/tmp/myprogram.XXXXXX».

mky ★★★★★
()
Ответ на: комментарий от mky

а запущенный через exec() процесс должен знать это имя, допустим через параметр командной строки, а не создавать файл «/tmp/myprogram.XXXXXX».

Не смею спорить, но разве это stream = fopen(filename, «r+»); создает файл а не только открывает ? http://www.linuxlib.ru/manpages/FOPEN.3.shtml

Если вы не понимате что это, то удалите пустые строки и пропустите ваш фарш через команду indent, можно с опцией -kr.

Извиняюсь, но в окне создания сообщения я не могу вставлять отступы. А команду indent где искать? Linuxa под рукой нету.

cyberovskij
() автор топика

во зацени, зупускатор чилдов


int open_children(char* filename, char *argv[], int fdesc[3], pid_t *child_pid)
{
 pid_t pid;
 int writepipe[2]; /* parent -> child */
 int readpipe[2]; /* child -> parent */
 int errorpipe[2]; /* child error -> parent */
 int r;
 char *szPing = "Ping";
 char szPingIn[4];
 
 
 
#define PARENT_READ     readpipe[0]
#define CHILD_WRITE     readpipe[1]
#define CHILD_READ      writepipe[0]
#define PARENT_WRITE    writepipe[1]
#define PARENT_READ_ERROR     errorpipe[0]
#define CHILD_WRITE_ERROR     errorpipe[1]

 if (pipe(writepipe)) return -1;
 if (pipe(readpipe))
 {
   close(writepipe[0]);close(writepipe[1]);
   return -2;
 }
 if (pipe(errorpipe))
 {
   close(writepipe[0]);close(writepipe[1]);
   close(readpipe[0]);close(readpipe[1]);
   return -3;
 }

 if((pid=fork()) == -1) return -4;
 
 if(pid)
 {
 
  close(CHILD_READ);
  close(CHILD_WRITE);
  close(CHILD_WRITE_ERROR);
  *child_pid = pid; 
  //wait to child ready
  szPingIn[0] = 0;
  r = read(PARENT_READ,szPingIn,4);
  if ((r<4) || (szPingIn[0] != szPing[0]))
  {
    close(PARENT_READ);close(PARENT_WRITE);close(PARENT_READ_ERROR);
    return -5;
  }
  
  fdesc[0] = PARENT_READ;
  fdesc[1] = PARENT_WRITE;
  fdesc[2] = PARENT_READ_ERROR;
  return 0;
 }
  
 close(PARENT_READ);close(PARENT_WRITE);close(PARENT_READ_ERROR);
 dup2(CHILD_READ, 0);
 dup2(CHILD_WRITE, 1);
 dup2(CHILD_WRITE_ERROR, 2);
 for(int i=3; i<20; i++) close(i); // :-)

 r = write(1,szPing,4);
 if (r<4) 
 {
  exit(1);	 
 }
 
 char* *targv;
 if (argv == NULL)
 {
   targv = malloc(sizeof(char*)*2);
   targv[0] = filename;
   targv[1] = 0;
 }
 else
 {
   targv = argv;
 }
 
 if(execv(filename, targv))
 {
  printf("Can't execute child, errno: %d, file: %s\n",errno,filename);
  exit(3);
 }
 
 printf("System unstable!!!, errno: %d, file: %s\n",errno,filename);
 exit(100); //WOW
}


ACR
()
Ответ на: во зацени, зупускатор чилдов от ACR

хороший запускатор. но мне не нужно наворотов. Есть исходный текст родителя который множится в определенный момент и получает данные из чайлда через файл (а не через канал). А задача стоит в том чтобы переделать чайлд так чтобы он был отдельной прогой но делал все тоже что и до того. Все что мне нужно, это чтобы мне указали на ошибки в коде если такие имеются.

cyberovskij
() автор топика
Ответ на: комментарий от cyberovskij

>fopen(filename, «r+»); создает файл а не только открывает ?

Не знаю, смотреть лень. Просто в main(), который в main2.c, с помощью mkstemp() шаблон «/tmp/myprogram.XXXXXX» преобразуется к уникальному имени файла, допустим «/tmp/myprogram.123456». А в child2.c открывается файл «/tmp/myprogram.XXXXXX», именно с XXXXXX, а не с числами.

А команду indent где искать? Linuxa под рукой нету.

Это вы зря... До свидания.

mky ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.