2015-02-28 2 views
0

Я думаю, что я понимаю, как работает fork(), но выполняются только некоторые из моих утверждений в теле. Например, в каждом блоке преобразования, все Е() будет выполнять еще png_count, gif_count и bmp_count никогда не увеличиваем и остаются 0 (как видно в Е() выход для ребенка (х);C, Некоторые утверждения в fork() не выполняются

/* Create Processes */ 
    printf("\n+++++++++++CREATING PROCESSES+++++++++++\n"); 
    int i, pid; 
    png_count = 0; 
    gif_count = 0; 
    bmp_count = 0; 

for(i = 0; i < convert_count; i++) { 
     pid = fork(); 
     if(pid < 0) { 
      printf("Error: fork failed"); 
      exit(1); 
     } 
     else if (pid == 0) { 
      /* Child execution */ 

      /* PNG conversion */ 
      if ((getpid() % 2) == 0) { 
       image_in_path = getInPath(input_dir, png_images[png_count]); 
       image_out_path = getOutPath(output_dir, png_images[png_count]); 
       printf("image_in_path: %s\n", image_in_path); 
       printf("Child (%d): %d\n", png_count+1, getpid()); 
       png_count++; 
       printf("Converting: %s\n", image_in_path); 
       execlp("convert", "convert", image_in_path, "-resize", "200x200", image_out_path, NULL); 
       exit(1); 
      } 
      /* GIF conversion */ 
      else if ((getpid() % 3) == 0) { 
       image_in_path = getInPath(input_dir, gif_images[gif_count]); 
       image_out_path = getOutPath(output_dir, gif_images[gif_count]); 
       printf("image_in_path: %s\n", image_in_path); 
       printf("Child (%d): %d\n", gif_count+1, getpid()); 
       gif_count++; 
       printf("Converting: %s\n", image_in_path); 
       execlp("convert", "convert", image_in_path, "-resize", "200x200", image_out_path, NULL); 
       exit(1); 
      } 
      /* BMP conversion */ 
      else { 
       image_in_path = getInPath(input_dir, bmp_images[bmp_count]); 
       image_out_path = getOutPath(output_dir, bmp_images[bmp_count]); 
       printf("image_in_path: %s\n", image_in_path); 
       printf("Child (%d): %d\n", bmp_count+1, getpid()); 
       bmp_count++; 
       printf("Converting: %s\n", image_in_path); 
       execlp("convert", "convert", image_in_path, "-resize", "200x200", image_out_path, NULL); 
       exit(1); 
      } 
     } 
     else { 
      /* Parent Execution */ 
      wait(NULL); 
     } 
    } 

выхода:

+++++++++++CREATING PROCESSES+++++++++++ 

image_in_path: idir/panda.bmp 
Child (1): 5389 
Converting: idir/panda.bmp 
image_in_path: idir/panda.bmp 
Child (1): 5393 
Converting: idir/panda.bmp 
image_in_path: idir/penguin.gif 
Child (1): 5397 
Converting: idir/penguin.gif 
image_in_path: idir/bmp.png 
Child (1): 5402 
Converting: idir/bmp.png 
image_in_path: idir/bmp.png 
Child (1): 5408 
Converting: idir/bmp.png 
image_in_path: idir/panda.bmp 
Child (1): 5413 
Converting: idir/panda.bmp 
image_in_path: idir/panda.bmp 
Child (1): 5417 
Converting: idir/panda.bmp 
image_in_path: idir/penguin.gif 
Child (1): 5421 
Converting: idir/penguin.gif 
image_in_path: idir/panda.bmp 
Child (1): 5425 
Converting: idir/panda.bmp 
image_in_path: idir/panda.bmp 
Child (1): 5429 
Converting: idir/panda.bmp 

заранее спасибо за помощь, я потратил слишком много часов, пытаясь понять это, не повезло

+0

Переменные прирастают, но они только увеличиваются в дочернем. Затем выполняются дочерние exec и увеличивается инкрементное значение. –

+0

Вы пытались использовать отладчик, например gdb, чтобы отметить, что на самом деле происходит? – user3629249

+0

Вы должны выполнить 'fflush (NULL);' перед 'fork()' –

ответ

3

раздвоенных дочерние процессы получают копию из их родителя. памяти (и s hare наиболее открытые дескрипторы файлов с их родителями и братьями и сестрами).

Они делают не все доля та же память, поэтому изменение переменной у ребенка не будет иметь никакого влияния на родителей или брата.

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

1
a programmer should always be very familiar with the system functions they call in their code. 
the main thing to notice is a child gets a COPY of the parents data, not access to the actual data. 

here is a copy of the 'man fork' output. 

FORK (2) Руководство программиста Linux FORK (2)

ИМЯ вилы - создать дочерний процесс

СИНТАКСИС #include

pid_t fork(void); 

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

* The child has its own unique process ID, and this PID does not match 
     the ID of any existing process group (setpgid(2)). 

    * The child's parent process ID is the same as the parent's process 
     ID. 

    * The child does not inherit its parent's memory locks (mlock(2), 
     mlockall(2)). 

    * Process resource utilizations (getrusage(2)) and CPU time counters 
     (times(2)) are reset to zero in the child. 

    * The child's set of pending signals is initially empty (sigpend‐ 
     ing(2)). 

    * The child does not inherit semaphore adjustments from its parent 
     (semop(2)). 

    * The child does not inherit record locks from its parent (fcntl(2)). 

    * The child does not inherit timers from its parent (setitimer(2), 
     alarm(2), timer_create(2)). 

    * The child does not inherit outstanding asynchronous I/O operations 
     from its parent (aio_read(3), aio_write(3)), nor does it inherit any 
     asynchronous I/O contexts from its parent (seeio_setup(2)). 

    The process attributes in the preceding list are all specified in 
    POSIX.1-2001. The parent and child also differ with respect to the 
    following Linux-specific process attributes: 

    * The child does not inherit directory change notifications (dnotify) 
     from its parent (see the description of F_NOTIFY in fcntl(2)). 

    * The prctl(2) PR_SET_PDEATHSIG setting is reset so that the child 
     does not receive a signal when its parent terminates. 

    * Memory mappings that have been marked with the madvise(2) MADV_DONT‐ 
     FORK flag are not inherited across a fork(). 

    * The termination signal of the child is always SIGCHLD (see 
     clone(2)). 

    Note the following further points: 

    * The child process is created with a single thread — the one that 
     called fork(). The entire virtual address space of the parent is 
     replicated in the child, including the states of mutexes, condition 
     variables, and other pthreads objects; the use of pthread_atfork(3) 
     may be helpful for dealing with problems that this can cause. 

    * The child inherits copies of the parent's set of open file descrip‐ 
     tors. Each file descriptor in the child refers to the same open 
     file description (see open(2)) as the corresponding file descriptor 
     in the parent. This means that the two descriptors share open file 
     status flags, current file offset, and signal-driven I/O attributes 
     (see the description of F_SETOWN and F_SETSIG in fcntl(2)). 

    * The child inherits copies of the parent's set of open message queue 
     descriptors (see mq_overview(7)). Each descriptor in the child 
     refers to the same open message queue description as the correspond‐ 
     ing descriptor in the parent. This means that the two descriptors 
     share the same flags (mq_flags). 

    * The child inherits copies of the parent's set of open directory 
     streams (see opendir(3)). POSIX.1-2001 says that the corresponding 
     directory streams in the parent and child may share the directory 
     stream positioning; on Linux/glibc they do not. 

ВОЗВРАТ СТОИМОСТИ В случае успеха, PID из дочерний процесс возвращается в родительском, а 0 возвращается в дочернем. При сбое в родительском элементе возвращается -1, не создается дочерний процесс, а errno устанавливается соответствующим образом.

ОШИБКИ EAGAIN fork() не может выделить достаточную память для копирования таблиц страниц родителя и распределения структуры задачи для дочернего элемента.

EAGAIN It was not possible to create a new process because the caller's 
      RLIMIT_NPROC resource limit was encountered. To exceed this 
      limit, the process must have either the CAP_SYS_ADMIN or the 
      CAP_SYS_RESOURCE capability. 

    ENOMEM fork() failed to allocate the necessary kernel structures 
      because memory is tight. 

СООТВЕТСТВИЕ SVr4, 4.3BSD, POSIX.1-2001.

ПРИМЕЧАНИЯ Под Linux, вилка() реализуется с помощью копирования при записи страниц, поэтому только штраф, который он берет время и объем памяти, необходимый для dupli- Cate таблиц страниц родительского, и создать уникальная структура задач для ребенка.

Since version 2.3.3, rather than invoking the kernel's fork() system 
    call, the glibc fork() wrapper that is provided as part of the NPTL 
    threading implementation invokes clone(2) with flags that provide the 
    same effect as the traditional system call. The glibc wrapper invokes 
    any fork handlers that have been established using pthread_atfork(3). 

Пример См трубу (2) и подождать (2).

ТАКЖЕ клона (2), execve (2), setrlimit (2), закрытие доступа (2), vfork (2), подождать (2), dae- ПН (3), возможности (7), учетные данные (7)

COLOPHON Эта страница является частью выпуска 3.23 проекта man man pages. A описание проекта, а также информацию об ошибках, может быть можно найти по адресу: http://www.kernel.org/doc/man-pages/.

Linux 2009-04-27 FORK (2)

Смежные вопросы