溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

信號量實現(xiàn)進程之間通信

發(fā)布時間:2020-07-10 01:16:46 來源:網絡 閱讀:919 作者:mdd9502053669 欄目:編程語言

一.信號量

   信號量是一種數(shù)據(jù)操作鎖,本身不具有數(shù)據(jù)交換功能,而是通過控制其他的通信資源來實現(xiàn)進程之間的通信,簡單來講,信號量相當于一個計數(shù)器,計數(shù)當前某種資源的個數(shù)。信號量的周期也是隨內核的。為了解決多個程序同時訪問一個共享資源引發(fā)的問題。

    臨界資源:多個進程能訪問到的公共資源。

    臨界區(qū):將能訪問帶臨界資源的代碼成為臨界區(qū)。

  同步:對臨界資源的訪問具有順序性。

   pv 操作:

   p(sv)  sv>0 減1  sv=0   掛起的該進程執(zhí)行

   s(sv)  沒有進程因等待sv而掛起就加1,有進程等待sv被掛起,就恢復運行。

  信號量用到的函數(shù):

  int semget(key_t key,int nsems,int smflag)//nsems:信號量個數(shù)

  以信號量集為基本單位進行申請。

 int semctl(int semid, int semnum, int cmd, ...);//semnum:第幾個信號量

   struct sembuf

{

   unsigned short sem_num;

   short sem_op;

   short sem_flg;

}

第一個成員,sem_num,是信號量數(shù)目,通常為0,除非我們正在使用一個信號量數(shù)組。sem_op成員是信號量的變化量值。(我們可以以任何量改變信 號量值,而不只是1)通常情況下中使用兩個值,-1是我們的P操作,用來等待一個信號量變得可用,而+1是我們的V操作,用來通知一個信號量可用。

最后一個成員,sem_flg,通常設置為SEM_UNDO。這會使得操作系統(tǒng)跟蹤當前進程對信號量所做的改變,而且如果進程終止而沒有釋放這個信號量, 如果信號量為這個進程所占有,這個標記可以使得操作系統(tǒng)自動釋放這個信號量。將sem_flg設置為SEM_UNDO是一個好習慣,除非我們需要不同的行為。如果我們確實變我們需要一個不同的值而不是SEM_UNDO,一致性是十分重要的,否則我們就會變得十分迷惑,當我們的進程退出時,內核是否會嘗試清理我們的信號量。

semnu 的聯(lián)合體,初始化信號量的時候用得到:

union semun {
    int val;
   struct semid_ds *buf;
   unsigned short *array;
           };




   信號量實現(xiàn)進程間通信:

 //comm.h
  1 
  2 #pragma once
  3 #include<unistd.h>
  4 #include<stdlib.h>
  5 #include<stdio.h>
  6 #include<sys/types.h>
  7 #include<sys/sem.h>
  8 #include<sys/ipc.h>
  9 #define _PATH_ "."
 10 #define _PROJ_ID_ 0x7777
 11 
 12 union semun
 13 {
 14    int val;
 15    struct semid_ds *buf;
 16    unsigned short *array;
 17    struct seminfo *_buf;
 18 };
 19  static int comm(int __sem_nums,int flag);
 20 int create_sem_set(int _sem_nums);
 21 int get_sem_set(int _sem_nums);
 22 int init_sem_set(int _sem_id,int _sem_num,int _sem_val);
 23 int p_sem_elem(int _sem_id ,int _sem_num);
 24 int v_sem_elem(int _sem_id,int _sem_num);
 25 int destroy_sem(int _sem_id);
~ 

//comm.c

  1 #include"comm.h"
  2 static int comm(int _sem_nums,int flag)
  3 {
  4   key_t key=ftok(_PATH_,_PROJ_ID_);
  5   if(key<0)
  6   {
  7     perror("ftok");
  8     return -1;
  9   }
 10   int sem_id=semget(key,_sem_nums,flag);
 11   if(sem_id<0)
 12   {
 13     perror("semget");
 14     return -1;
 15   }
 16 
 17   return sem_id;
 18 
 19 }
 20  int create_sem_set(int _sem_nums)
 21 {
 22   int flag=IPC_CREAT|IPC_EXCL|0666;
 23   return comm(_sem_nums,flag);
 24 
 25 
 26 }
 27 int get_sem_set(int _sem_nums)
 28 {
 29    int flag=IPC_CREAT;
 30    return comm(_sem_nums,flag);
 31 }
 32 int init_sem_set(int _sem_id,int _sem_num,int _sem_val)
 33 {
 34    union semun _un;
 35    _un.val=_sem_val;
 36    if(semctl(_sem_id,_sem_num,SETVAL,_un)<0)
 37    {
 38     perror("semctl");
 39     return -1;
 40 
 41     }
 42    return 0;
 43   }
 44 int p_sem_elem(int _sem_id ,int _sem_num)
 45 {
 46    struct sembuf _sem_buf[1];
 47    _sem_buf[0].sem_num=_sem_num;
 48    _sem_buf[0].sem_op=-1;
 49    _sem_buf[0].sem_flg=0;
 50 if(semop(_sem_id,_sem_buf,1)<0)
 51   {
 52   perror("semop");
 53   return -1;
 54 
 55   }
 56   return 0;
 57 }
 58 int v_sem_elem(int _sem_id,int _sem_num)
 59 {
 60    struct sembuf _sem_buf[1];
 61    _sem_buf[0].sem_num=_sem_num;
 62    _sem_buf[0].sem_op=1;
 63    _sem_buf[0].sem_flg=0;
 64 if(semop(_sem_id,_sem_buf,1)<0)
 65   {
 66     perror("semop");
 67     return -1;
 68 
 69   }
 70   return 0;
 71 
      }
 74 int destroy_sem(int _sem_id)
 75 {
 76   if(semctl(_sem_id,0,IPC_RMID,NULL)<0)
 77   {
 78   perror("semctl");
 79    return -1;
 80 
 81 
 82   }
 83 return 0;
   }
   
   
 91 int main()
 92 {
 93   int sem_id=create_sem_set(1);
 94   init_sem_set(sem_id,0,1);
 95   pid_t pid=fork();
 96   if(pid<0)
 97   {
 98    perror("fork");
 99    exit(1);
100   }
101 
102   else if(pid==0)
103   {
104       int sem_id=get_sem_set(1);
105       while(1)
106       {
107         p_sem_elem(sem_id,0);
108         printf("A");
109         sleep(1);
110        fflush(stdout);
111        printf("A");
112        sleep(7);
113        fflush(stdout);
114        v_sem_elem(sem_id,0);                                                         116      }
117  }
118 
119   else
120   {
121      while(1)
122     {
123       p_sem_elem(sem_id,0);
124 
125       printf("B");
126       sleep(2);
127       fflush(stdout);
128       printf("B");
129       sleep(5);
130       fflush(stdout);
131       v_sem_elem(sem_id,0);
132 
133 
134     }
135  }                                                                                        return 0;
   }

程序運行結果:

信號量實現(xiàn)進程之間通信

總結:

   上述程序中顯示器就相當于公共資源,父子進程都想要訪問,在其上面輸出自己的內容,就必須使用信號量,這樣就防止了兩個同時輸出引發(fā)的問題,兩個進程只能一個訪問完,另一個在訪問。





向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

AI