父子进程之间的POSIX信号量

时间:2019-11-28 09:32:54

标签: c++ c posix semaphore

我希望从父进程和子进程中交替获得以下输出

parent : 2 x 1 = 2
child : 2 x 2 = 4
parent : 2 x 3 = 6
 .
 .
child : 2 x 10 = 20

我已经使用信号量尝试了以下代码。

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

sem_t mutex_odd,mutex_even;

int main()
{  
   int o=1;e=2;
   pid_t pid = fork();
   sem_init(&mutex_odd,0,1);
sem_init(&mutex_even,0,1);
if(pid>0)
{
while(o<=9)
{
  sem_wait(&mutex_even);
  printf("parent : 2 x %d = %d\n", o, 2*o); 
  o+=2;
  sem_post(&mutex_odd);
}
}
else if(pid == 0)
{
while(e<=10)
{
   sem_wait(&mutex_odd);
   printf("parent : 2 x %d = %d\n", e, 2*e); 
   e+=2;
   sem_post(&mutex_even);
}
}
else
{
   printf("Child process couldn't be created!\n");
   exit(0);
}
return 0;
}

但是输出如下所示。控制权只停留在那儿而不终止程序。

parent : 2 x 1 = 2
child : 2 x 2 = 4

这是一个僵局吗?如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

当父进程派生时,其子进程将继承父进程正在管理的值的COPY。副本不使用相同的物理内存区域;还有内存指针,尽管看起来它们具有相同的地址值,但它们并不指向相同的物理内存区域。

获取父级和子级共享内存的方法是使用IPC(进程间通信)功能。

下面的程序使用IPC函数:shmgetshmat分配内存以管理信号量(变量mutex),并使用函数shmdt来“解除分配” mutex数组指针和smdctl来删除分配的物理内存。

您的代码的另一个问题是信号量的初始化。在分叉进程之间共享时,第二个参数(pshared)应该为1。为了避免同步问题,第三个参数(value)最好将互斥锁设置为1。父进程等待,并将子进程等待的互斥锁设置为0。

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

#include <pthread.h>
#include <sys/wait.h>

#include <sys/ipc.h>
#include <sys/shm.h>

    static sem_t * mutex;

    int main()
    {
        int o=1,e=2,r;
        pid_t pid;
        int shmid=0;

        shmid=shmget(0,sizeof(mutex)*2 + SHMLBA, IPC_CREAT | SHM_R | SHM_W);
        if (shmid==-1) {
            perror("shmget");
            return errno;
        }

        mutex=shmat(shmid, NULL, 0);
        if (mutex== (void *) -1){
            perror("shmat");
            return errno;
        }

        r=sem_init(&mutex[0],1,1);
        if (r) {
            perror("m0");
            return errno;
        }

        r=sem_init(&mutex[1],1,0);
        if (r) {
            perror("m1");
            return errno;
        }

        pid=fork();
        if(pid>0)
        {
            while(o<=9)
            {
                sem_wait(&mutex[0]);
                printf("parent : 2 x %d = %d\n", o, 2*o);
                o+=2;
                sem_post(&mutex[1]);
            }

            // Waits end of
            waitpid(pid,NULL,0); // Waits end of child
            puts("End");

            r=shmdt(mutex);                   // Free memory
            if (r)
                perror("shmdt");

            r=shmctl(shmid,IPC_RMID,NULL);    // Remove map id.
            if (r)
                perror("shmctl");
        }
        else if(pid == 0)
        {
            while(e<=10)
            {
                sem_wait(&mutex[1]);
                printf("child : 2 x %d = %d\n", e, 2*e);
                e+=2;
                sem_post(&mutex[0]);
            }
        }

        /*---------------------*/
        else
        {
            perror("Child process couldn't be created!\n");
            exit(0);
        }
        return 0;
    }