Process 下面的代码仅优先于它';s修改共享变量的第一个子项。如何删除此错误?

Process 下面的代码仅优先于它';s修改共享变量的第一个子项。如何删除此错误?,process,signals,ipc,shared-memory,Process,Signals,Ipc,Shared Memory,我希望捕获所有子进程对父进程的共享变量所做的更改 问题就在这里。 父进程创建如下结构: struct data { int pid; int n; char c; }; 它创建k个进程,并与所有子进程共享该结构。变量c被初始化为“n”,并用作标志 家长在一段随机时间(不超过2秒)后定期“唤醒”(从“睡眠”)检查c的值,如果c为“y”,则打印n的值(以及相应的pid),并使c再次为“n” 另一方面,每个孩子Pi,1≤ 我≤ k、 在一段随机时间(不

我希望捕获所有子进程对父进程的共享变量所做的更改

问题就在这里。 父进程创建如下结构:

struct data
{
        int pid;
        int n;
        char c;
};
它创建k个进程,并与所有子进程共享该结构。变量
c
被初始化为“n”,并用作标志

家长在一段随机时间(不超过2秒)后定期“唤醒”(从“睡眠”)检查c的值,如果c为“y”,则打印n的值(以及相应的pid),并使c再次为“n”

另一方面,每个孩子Pi,1≤ 我≤ k、 在一段随机时间(不超过2秒)后定期“唤醒”(从“睡眠”)检查c的值,如果c为“n”,则将一些随机值分配给n,并将其进程id分配给pid,打印该值及其自己的进程id,并使c为“y”

如果程序执行被用户终止(按Ctrl-C键),则父级及其所有子级都应终止,并且应重新分配分配的内存

代码如下:

typedef void (*sighandler_t)(int);
int shmid;

struct data
{
        int pid;
        int n;
        char c;
};

void releaseSHM(int signum)
{
        int status;
        status = shmctl(shmid, IPC_RMID, NULL);
        if (status == 0)
                fprintf(stderr, "Remove shared memory with id = %d.\n", shmid);
        else if (status == -1)
                fprintf(stderr,"Cannot remove shared memory of id = %d.\n", shmid);
        else
                fprintf(stderr, "shmctl() returned wrong value while removing shared memory with id = %d.\n", shmid);



        status = kill(0, SIGKILL);
        exit(signum);
}

int main(int argc, char *argv[])
{
        int num,k=5,i, p1;
        struct data *s;

        sighandler_t shandler;

        shandler =  signal(SIGINT, releaseSHM);

        shmid =  shmget(IPC_PRIVATE, sizeof(struct data), IPC_CREAT | 0777);
        if(shmid==-1)
        {
                perror("shmget() failed");
                exit(1);
        }

        s=(struct data *)shmat(shmid, NULL, 0);
        s->c='n';

        for(i=0;i<k;i++)
        {
                p1=fork();
                if(p1==0)
                {
                        while(1)
                        {
                                //shandler =  signal(SIGINT, releaseSHM);
                                num=(rand()%3);
                                sleep(num);
                                if(s->c=='n')
                                {
                                                s->n=rand();
                                                s->pid=getpid();
                                                printf("Child with pid %d set value of n as %d \n",s->pid,s->n);
                                                s->c='y';
                                }
                                sleep(num);
                        }
                }
                else
                {
                        while(1)
                        {
                                num=(rand()%3);
                                sleep(num);
                                if(s->c=='y')
                                        printf("Parent reads value of n as %d set by child with process id %d \n",s->n, s->pid);
                                s->c='n';
                        }
                }
        }
        return 0;
}
显然,它只捕获一个子进程所做的更改,而不给其他子进程机会。如何删除此错误


如果需要任何其他信息,请在下面添加注释。

您打算让父级和k个子级争夺共享内存,但不管k的值是多少,您只生成一个子级

你这样写:

....
for (int i = 0; i < k; i++) {
  pid_t child = fork();
  if (child == 0) do_child_infinite_loop();
  else do_parent_infinite_loop(); // <- BUG: the for loop never resumes
}
。。。。
for(int i=0;i否则,您希望有一个父级和k个子级争用共享内存,但不管k的值是多少,您只生成一个子级

你这样写:

....
for (int i = 0; i < k; i++) {
  pid_t child = fork();
  if (child == 0) do_child_infinite_loop();
  else do_parent_infinite_loop(); // <- BUG: the for loop never resumes
}
。。。。
for(int i=0;ielse do_parent_infinite_loop();//您只创建了一个子进程;父进程在第一个
fork()之后进入无限循环,并且从不创建另一个子进程。@pilcrow但是无限循环是必要的,因为它声明子进程“定期”唤醒并检查c的值……对。您只创建了一个子进程。将父进程的无限循环移到
for
循环之外。@pilcrow在这种情况下,会创建任意数量的子进程,但我需要将其限制为k个子进程。您只创建了一个子进程;父进程在第一个
fork()
,永远不会创建另一个子进程。@pilcrow但无限循环是必要的,因为它表示子进程“定期”唤醒并检查c的值。……对。您只创建了一个子进程。将父进程的无限循环移到
for
循环之外。@pilcrow在这种情况下,创建了任意数量的子进程,但我需要将其限制为k个子进程。这是绝对正确的。我已经检查了。但是如果您打印进程id,则child_infinite_循环您将看到创建了任意数量的进程(不限于k,事实上大于k)。虽然较旧创建的进程会被重新调度,并有公平的CPU机会。@Hamsa,生成子进程>k是代码中的另一个错误,但您在这里并没有显示。也许会提出另一个问题?这绝对正确。我已经检查过了。但若您打印进程id的子进程无限循环,您会发现任意数量的进程都是created(不限于k,事实上大于k)。虽然较旧的创建进程会被重新调度,并有公平的CPU机会。@Hamsa,生成子进程>k是代码中的另一个bug,您在这里并没有显示。也许会提出另一个问题?
....
for (int i = 0; i < k; i++) {
  pid_t child = fork();
  if (child == 0) do_child_infinite_loop();
}
do_parent_infinite_loop();