IPC之——信号量集(多个信号量)

时间:2022-08-29 20:41:33

如果两个进程不仅需要同步,还要保证先后执行顺序,就要用两个信号量(互斥锁)来解决

//栅栏模型:实现以下框架中的四个子进程 所有进程做完任务后 在一起执行下一次  
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdlib.h>
#include <signal.h>

#define     PROCESS_NR        4
void sigFunc(int signo)
{
    int semId;
    semId=semget(0x555,PROCESS_NR+1,IPC_CREAT|0600);
    if(semId>0){
       semctl(semId,0,IPC_RMID);
    }
    exit(1);
}

void p_lock(int idx,int semId);
void waitZero(int semId);

void  doWork(int idx,int semId);

int main(void)
{
     int  semId,i;
     pid_t  pid;
     ////////////////////////////////
     //对应的下标的信号量控制对应的子进程  最后一个信号量控制父进程
     semId=semget(0x555,PROCESS_NR+1,IPC_CREAT|0600);
     if(semId==-1)
     {
         perror("create sem");
         return 11;
     }
     //init sem value
     unsigned short  vals[PROCESS_NR+1]={0};//对多个信号量值进行初始化
     if(semctl(semId,0,SETALL,vals)==-1)
     {
          perror("init sem val");
          semctl(semId,0,IPC_RMID);
          return 12;
     }
     ////////////////////////////////
     for(i=0;i<PROCESS_NR;i++)
     {
          pid=fork();
          if(pid==-1)  return 1;
          else if(pid==0)//child process
          {
              doWork(i,semId);//i标识进程的编号
              exit(0);
          }
     }
     //
     signal(SIGINT,sigFunc);
     //parent
     struct sembuf  bufs[PROCESS_NR+1]={0};
     for(i=0;i<PROCESS_NR;i++)//子进程
     {
          bufs[i].sem_num=i;
          bufs[i].sem_op =1;
     }
     bufs[PROCESS_NR].sem_num=PROCESS_NR;//父亲的资源
     bufs[PROCESS_NR].sem_op =PROCESS_NR;

     ////////////////////////////////////////
     while(1)
     {
          waitZero(semId);
          printf("========升起栅栏=======\n");
          semop(semId,bufs,PROCESS_NR+1);
     }

     while(wait(NULL)!=-1)
        ;//empty
     return 0;
}
void  doWork(int idx,int semId)
{
      pid_t pid=getpid();
      int   sec;

      srand(pid);

      while(1)
      {
          p_lock(idx,semId);

          sec=rand()%10+1;
          printf("%dth Do [%d] sec:%d\n",idx,pid,sec);
          //随机休眠1-10s 模拟不同进程不同时侯做事情可能需要不同的时长
          sleep(sec);

          //通知父进程 该子进程已执行完毕
          p_lock(PROCESS_NR,semId);
      }
}

////////////////////////////////////////
void p_lock(int idx,int semId)
{
      struct sembuf  buf={.sem_num=idx,.sem_op=-1};

      semop(semId,&buf,1);
}
void waitZero(int semId)
{
      struct sembuf  buf={.sem_num=PROCESS_NR,.sem_op=0};

      semop(semId,&buf,1);
}