Linux--進程間通信-信號量

一、什麼是信號量

    就是一種用來描述某種資源數量個數的計數器,通過控制其他通信資源來實現進程通信。它在此過程中負責數據的互斥、同步等。互斥,就是在同一時間段內,A、B兩個進程只有一個進程在運行。同步。就是A 進程完成之後,B進程接着完成,有一定的執行順序。

二、工作原理

    兩種操作模式,P操作和V操作。

    P操作(就是申請資源,信號量進行減一操作)

    V操作(釋放資源,信號量進行加一操作)

三、 ipcs -s 查看semid

   ipcrm -s id 刪除id

四、主要函數

    shmget 創建信號量

    shmctl 刪除

    shmop P/V 操作

    函數原型: int semop(int sem_id,struct sembuf *sops,size_t nsops);

    sem_id 就是通過shmget函數創建得到的

    struct sembuf *sops 參數sops指向一個結構體數組中,每個sembuf結構體對應一個信號的操作。結構體如下

     struct sembuf

    {

        unsigned short sem_num;//sem_num是信號集中的索引,0代表第一個,1,代表第二個。。。    

        short     sem_op; //操作類型,1 -->V操作,-1-->P操作

        short     sem_flg; //操作標誌   

 };

    sem_flg標誌有兩種 IPC_NOWAIT 或 SEM_UNDO 兩種。如果操作指定 SEM_UNDO(我下面給的是0),它將會自動撤銷該進程在終止時

     nsops 就是sops 的個數

~~ ~~~~~~~~~~ ~~~~********** man 函數名可查看函數的用法**********~~~~~~~~~~~~~~~~~~~

五、代碼實現

    comm.h

   #pragma once
   #include<stdio.h>
   #include<stdlib.h>
   #include<unistd.h>
   #include<sys/types.h>
   #include<sys/ipc.h>
   #include<sys/sem.h>
   #define _PATH_ "."
   #define _PROG_ID_ 0x6675
  
   union semun
   {
      int val;
      struct semid_ds *buf; 
      unsigned short *array;
      struct seminfo *__buf;
  };
  int creatSem(int nsems);
  int get_Sem();
  int initSem(int sem_id,int Which);
  int destroySem(int sem_id);
  int V_Sem(int sem_id,int which);
  int P_Sem(int sem_id,int which);
  static int op_Sem(int sem_id,int op,int which);

 comm.c

   #include"comm.h"
   int creatSem(int nsems)
   {
       key_t  _key=ftok(_PATH_,_PROG_ID_);
       if(_key<0)
       {
           perror("ftok");
           return -1;
       }
      umask(0);
      int sem_Flg=IPC_CREAT|IPC_EXCL|0666;
      int sem_id=semget(_key,nsems,sem_Flg);
      if(sem_id<0)
      {
          perror("semget");
          return -1;
      }
      return sem_id;
  }
  
  int get_Sem()
  {
      key_t k=ftok(_PATH_,_PROG_ID_);
      return semget(k,0,0);
  }
  static int op_Sem(int sem_id,int op,int which)
  {
      struct sembuf sem;
      sem.sem_num=which;
      sem.sem_op=op;
      sem.sem_flg=0;
      return semop(sem_id,&sem,1);
  
  }
  
  int initSem(int sem_id,int Which)
  {
      union semun _semum;
      _semum.val=1;
     int ret= semctl(sem_id,Which,SETVAL,_semum);
     if(ret==-1)
     {
             perror("semctl");
             return ret;
     }
     return ret;
  }
  int P_Sem(int sem_id,int which)
  {
      int ret=op_Sem(sem_id,-1,which);
      if(ret==-1)
     {
          perror("p_sem");
          return -1;
      }
          return ret;
  
 }
  int V_Sem(int sem_id,int which)
  {
      int ret=op_Sem(sem_id,1,which);
      if(ret==-1)
      {
          perror("V_Sem");
          return ret;
      }
      return ret;
  }
  
  int destroySem(int sem_id)
  {
      int ret=semctl(sem_id,0,IPC_RMID,NULL);
      if(ret==-1)
      {
          perror("semtrl");
          return -1;
      }
      return ret;
  
  }

my_shm.c

    #include"comm.h"
   int main()
   {
        int sem_id=creatSem(1);
       initSem(sem_id,0);
       pid_t id=fork();
       if(id<0)
       {
           perror("for");
          return -1;
      }
      else if(id==0)
      {
          int sem_id=get_Sem();
          while(1)
         {
  
              P_Sem(sem_id,0);
              printf("A");
              fflush(stdout);
              sleep(1);
              printf("A");
              fflush(stdout);
              sleep(2);
              V_Sem(sem_id,0);
          }
  
      }else
      {
          while(1)
          {
              P_Sem(sem_id,0);
              printf("B");
              fflush(stdout);
              sleep(1);
              printf("B");
              fflush(stdout);
              sleep(1);
              V_Sem(sem_id,0);
          }
          waitpid(id,NULL,0);
      }
  
  }

 不用信號量之前(如下圖)可以看出打印結果是隨機的 。

wKioL1cQhX-BTurAAAFTOsROepo339.jpg 加了信號量之後(如下圖)(都是成對出現的,因爲是互斥的)

wKiom1cQhQ2TpqSrAAME82F-5Mk793.jpg

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章