Глобальные значения, измененные дочерним процессом, недоступны для родительского процесса в основном цикле - PullRequest
1 голос
/ 05 декабря 2011

В main() я вызываю функцию create_child(), которая разветвляет дочерний процесс, а затем выполняет команду, которая выполняется в фоновом режиме.Я использую getpid(), чтобы получить pid дочернего элемента в глобальной переменной, к которой обращается родительский элемент в основном цикле.Тем не менее, я не вижу значение дочернего pid в основном цикле.ниже псевдокод-

pid_t pids[2];

create_child(cmd,counter) {

 i=fork();
 if(i<0) exit(1);
 if(i==0) { 
   pids[counter]=getpid();
   ret=system(cmd);
   //when system returns exit 0;
  }
 }


 main() {
   counter=0;
   create_child(cmd,counter);
   if (pids[counter]==xxx) {

     -----
    }
 }

Ответы [ 3 ]

1 голос
/ 05 декабря 2011

Я использую getpid(), чтобы получить pid дочернего элемента в глобальной переменной, к которой обращается родительский элемент в основном цикле.

При выполнении fork для адресата создается копия адресного пространства родителя. Следовательно, у потомка будет копия переменных родителя, однако изменение любых переменных в родительском или дочернем элементе не приведет к изменениям, внесенным в другую.

Из справочника для fork:

В случае успеха PID дочернего процесса возвращается в родительском, а 0 - в дочернем.

Если вы хотите записать PID дочернего элемента в родительском элементе, пусть parent сохранит возвращаемое значение fork. Если возвращаемое значение fork не равно 0, то вы в родительском. Отсюда родителю нужно сохранить PID. то есть:

pid_t ret = fork();

if (ret < 0) { /* failed */ }
else if (ret == 0) { /* child, do exec */ }
else { /* parent, store PID */ }
0 голосов
/ 05 декабря 2011

1) Как только родитель разветвляет новый процесс, у нового процесса есть жизнь, и там у него есть свои собственные данные. Новый процесс наследует данные от родителя, и собственная копия Child создается, пока child пытается изменить данные. Этот концентрат называется CopyOnRight. Вот почему изменения, сделанные ребенком, не видны родителем. Даже если вы создаете элемент данных кучи [т.е. динамическое выделение памяти], применима та же концепция. Давайте возьмем следующий пример.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main (int arg, char ** argv )
{
    pid_t pid;
    int *p = malloc (sizeof(int));
    printf ("\n Globally Assigned 99 to *p\n ");
    *p= 99;

    pid = fork ();
    if (pid > 0)
    {
            printf ("\n Parent Changed *p to 100 \n ");
            *p=100;
            wait (NULL);
            printf (" Prent Exiting..\n");

    } else {
            sleep(10); /* I want to give preference to my parent :) */
            printf ("..Child fetching the value  *p is %d \n", *p);
    }

}

2). Как объяснил @Mathieu, труба также может использоваться для связи между двумя процессами. Давайте посмотрим на следующий пример кода, который использует общую память между родителем и ребенком. Сравните это с программой, приведенной в (1). Увидеть!!! Я не проверял ошибок, так как намерен спроектировать концепцию !!!.

#include <sys/mman.h>
#include <sys/stat.h>        
#include <fcntl.h>           
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>


int main ( int arg, char ** argv )
{
        int sId;
        int * ptr= NULL;
        pid_t pid;

        /* We create a shared memory object */
        sId = shm_open("MySharedData", O_RDWR|O_CREAT|O_TRUNC, 0666);

        /* We allocate memory to shared object */         
        ftruncate (sId, 512);

        /* we attach the allocated object to our process */
        ptr = (int *) mmap (NULL, 512, PROT_READ|PROT_WRITE, MAP_SHARED, sId, 0);
        printf ("\n Globally Assigned 99 to *p\n ");
        *ptr=99;
        pid = fork ();
        if (pid > 0)
        {
                printf ("\n Parent Changed *p to 100 \n ");
                *ptr=100;
                wait (NULL);
                printf (" Wow Child canged to %d \n", *ptr);
                printf (" Prent Exiting..\n");

        } else {
                sleep(10); /* I want to give preference to my parent :) */
                printf ("..Child fetching the value  *p is %d \n", *ptr);
                *ptr=1234;
        }
}

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

Надеюсь, это поможет !!!.

0 голосов
/ 05 декабря 2011

Вам понадобится труба, чтобы вернуть пид. при разветвлении дочерний объект наследует копию текущих переменных процесса. Если вы хотите сохранить какие-либо изменения, сделанные ребенком, вам нужно будет передать их родителю: псевдокод:

int fd[2];
int id;
pipe(fd);
id = fork();
if (id == 0)
{
    close (fd[0]);
    pid = getpid();
    write (fd[1], pid, nbytes)
    exit(0);
}
else
{
    close(fd[1]);
    read(fd[0], buffer, nbytes);
}

Теперь вы можете использовать буфер для изменения вашей глобальной переменной.

...