主循环中的父进程无法访问由子进程修改的全局值

时间:2011-12-04 23:56:21

标签: c ipc fork

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 个答案:

答案 0 :(得分:1)

  

我使用getpid()来获取全局变量中子项的pid,该变量在主循环中由访问

当您执行fork时,会为该孩子制作父母地址空间的副本。因此,子项将拥有父项变量的副本,但是修改父项或子项中的任何变量都不会看到对另一项变量的更改。

来自fork的联机帮助页:

  

成功时,父进程返回子进程的PID,并在子进程中返回0。

如果要在父项中记录子项的PID,请让父项存储fork的返回值。如果fork的返回值不为0,那么您就在父级中。从这里,让父存储PID。即:

pid_t ret = fork();

if (ret < 0) { /* failed */ }
else if (ret == 0) { /* child, do exec */ }
else { /* parent, store PID */ }

答案 1 :(得分:0)

你需要一根管子来取回pid。当你分叉时,孩子会继承进程当前变量的副本。如果要存储子进程所做的任何更改,则必须将它们传递给父进程: 伪代码:

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);
}

然后您可以自由使用缓冲区来修改全局变量。

答案 2 :(得分:0)

1)一旦父进程分叉了一个新进程,新进程就有了生命,并且它有自己的数据。新进程从父进程继承数据,并在子进程尝试修改数据时创建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)中,您可以看到父级已被子级修改的更改,反之亦然,因为共享内存是共享内存对于父/子都是通用的,而不是同时具有单独的内存位置。

希望这有助于!!!。