一、什麼是信號量
就是一種用來描述某種資源數量個數的計數器,通過控制其他通信資源來實現進程通信。它在此過程中負責數據的互斥、同步等。互斥,就是在同一時間段內,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); } }
不用信號量之前(如下圖)可以看出打印結果是隨機的 。