您好,登錄后才能下訂單哦!
信號量:相當于一個計數器,計錄當前環境某種資源個數。沒有對信號進行傳輸,保證對信號量操作是原子的。主要為了保護臨界資源。生命周期隨內核。
臨界區:訪問共享資源的代碼區
臨界資源:進程間所共享的資源
互斥:同一時刻,只允許一個進程對這份資源訪問,這個進程對資源具有獨占性,排他性。
同步:互斥情況下,進程對臨界資源訪問具有順序。
信號量有兩個基本操作:P,V
p:減一,向信號量申請資源,申請到后若p=0,則將進程掛起,否則信號量減一。
v:加一,使用資源完畢,歸還給系統,若有進程掛起,則喚醒等待進程或線程,否則將信號量加一。
使用到的主要函數原型:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
int semctl(int semid, int semnum, int cmd, ...);
int semop(int semid, struct sembuf *sops, unsigned nsops);
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
struct sembuf{
unsigned short sem_num; /* semaphore number */
short sem_op; /* semaphore operation */
short sem_flg; /* operation flags */
}中sem_flg表示以什么形式控制信號量,0表示默認,SEM_NODO表示取消
注意:信號量的創建是以信號量集的形式創建
當semctl(semid,semnum,cmd);要刪除時cmd被設置為IPC_RMID,semnum被忽視。當cmd為SETVAL時,對第semnum個信號量初始化。
信號量集中信號量從0開始
grep -ER 'semum' /usr/include/ 查詢semum
//comm.h 1 #pragma once 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<unistd.h> 5 #include<sys/types.h> 6 #include<sys/ipc.h> 7 #include<sys/sem.h> 8 #define _PATH_ "." 9 #define _PROJ_ID_ 0x8888 10 union semun 11 { 12 int val; 13 struct semid_ds* buf; 14 unsigned short *array; 15 struct seminfo *__buf; 16 }; 17 //struct sembuf 18 //{ 19 // unsigned short sem_num; 20 // short sem_op; 21 // short sem_flg; 22 // }; 23 static int _sem_set(int snum,int flags); 24 static int sem_op(int sem_id,int nsops,int flags); 25 int create_sem(int snum); 26 int get_sem(int snum); 27 int init_sem(int sem_id,int snum,int unit_val); 28 int sem_p_element(int sem_id,int nsops); 29 int sem_v_element(int sem_id,int nsops); 30 int destory_sem_element(int sem_id); //comm.c 1 #include"comm.h" 2 static int _sem_set(int snum,int flags) 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=-1; 11 sem_id=semget(_key,snum,flags); 12 if(sem_id<0) 13 { 14 15 perror("semget"); 16 return -1; 17 } 18 return sem_id; 19 } 20 21 int create_sem(int snum) 22 { 23 int flags=IPC_CREAT|IPC_EXCL|0666; 24 int ret= _sem_set(snum,flags); 25 return ret; 26 } 27 int get_sem(int snum) 28 { 29 return _sem_set(snum,IPC_CREAT); 30 } 31 int init_sem(int sem_id,int snum,int unit_val) 32 { 33 union semun _un; 34 _un.val=unit_val; 35 if(semctl(sem_id,snum,SETVAL,_un)<0) 36 { 37 perror("semctl\n"); 38 return -1; 39 } 40 return 0; 41 } 42 static int sem_op(int sem_id,int seqnum,int op) 43 { 44 struct sembuf _sm; 45 _sm.sem_num=seqnum; 46 _sm.sem_op=op; 47 _sm.sem_flg=0; 48 if(semop(sem_id,&_sm,1)<0) 49 { 50 perror("semop"); 51 return -1; 52 } 53 return 0; 54 } 55 int sem_p_element(int sem_id,int seqnum) 56 { 57 return sem_op(sem_id,seqnum,-1); 58 } 59 int sem_v_element(int sem_id,int seqnum) 60 { 61 return sem_op(sem_id,seqnum,1); 62 } 63 int destory_sem_element(int sem_id) 64 { 65 if(semctl(sem_id,IPC_RMID,0,NULL)<0) 66 { 67 perror("semctl\n"); 68 return -1; 69 } 70 return 0; 71 } //test.c 1 #include"comm.h" 2 int main() 3 { 4 int sem_id=create_sem(1); 5 if(sem_id<0) 6 { 7 printf("error\n"); 8 return -1; 9 } 10 init_sem(sem_id,1,1); 11 pid_t pid=fork(); 12 if(pid<0) 13 { 14 perror("pid"); 15 return -1; 16 } 17 else if(pid==0) 18 { 19 int sem_pid=get_sem(1); 20 while(1) 21 { 22 sem_p_element(sem_pid,0); 23 printf("A"); 24 sleep(1); 25 fflush(stdout); 26 printf("A"); 27 sleep(8); 28 fflush(stdout); 29 sem_v_element(sem_pid,0); 30 } 31 } 32 else 33 { 34 while(1) 35 { 36 sem_p_element(sem_id,0); 37 sleep(3); 38 printf("B"); 39 sleep(2); 40 fflush(stdout); 41 printf("B"); 42 sleep(5); 43 fflush(stdout); 44 sem_v_element(sem_id,0); 45 } 46 waitpid(pid,NULL,0); 47 destory_sem_element(sem_id); 48 49 } 50 return 0; 51 } //Makefile 1 .PHONY:all 2 all:test 3 test:test.c comm.c 4 gcc -o $@ $^ 5 .PHONY:clean 6 clean: 7 rm -f test
未使用信號量之前:
使用后:
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。