衆所周知,進程間通訊有三種方式,信號量、消息隊列和共享內存。不過信號量我的感受不像通訊,其實就是一個鎖的東西。html
這部份內容分幾個部分數據結構
1.API函數
建立信號量 int semget(key_t key,int nsems,int semflg); 返回值就是信號量標識semid spa
Sem_op
|
操 做
|
正數
|
釋放相應的資源數,將sem_op的值加到信號量的值上
|
0
|
進程阻塞直到信號量的相應值爲0,當信號量已經爲0,函數當即返回。若是信號量的值不爲0,則依據sem_flg的IPC_NOWAIT位決定函數動做。sem_flg指定IPC_NOWAIT,則semop函數出錯返回EAGAIN。sem_flg沒有指定IPC_NOWAIT,則將該信號量的semncnt值加1,而後進程掛起直到下述狀況發生。信號量值爲0,將信號量的semzcnt的值減1,函數semop成功返回;此信號量被刪除(只有超級用戶或建立用戶進程擁有此權限),函數smeop出錯返回EIDRM;進程捕捉到信號,並從信號處理函數返回,在此狀況將此信號量的semncnt值減1,函數semop出錯返回EINTR
|
負數
|
請求sem_op的絕對值的資源。若是相應的資源數能夠知足請求,則將該信號量的值減去sem_op的絕對值,函數成功返回。當相應的資源數不能知足請求時,這個操做與sem_flg有關。sem_flg指定IPC_NOWAIT,則semop函數出錯返回EAGAIN。sem_flg沒有指定IPC_NOWAIT,則將該信號量的semncnt值加1,而後進程掛起直到下述狀況發生:當相應的資源數能夠知足請求,該信號的值減去sem_op的絕對值。成功返回;此信號量被刪除(只有超級用戶或建立用戶進程擁有此權限),函數smeop出錯返回EIDRM:進程捕捉到信號,並從信號處理函數返回,在此狀況將此信號量的semncnt值減1,函數semop出錯返回EINTR
|
#include <stdio.h> #include <stdlib.h> #include <sys/ipc.h> #include <sys/types.h> #include <sys/sem.h> union semun//因爲類型是union 須要在這裏初始化一下 { int val; struct semid_ds *buf; unsigned short int *array; struct seminfo *__buf; }; int main(int argc, char const *argv[]) { int semid; key_t key; key=ftok(".",3); //ftok的做用就是計算一個key值供使用,通常用當前目錄文件結點索引號來計算,如指定文件的索引節點號爲65538,換算成16進製爲0x10002,而你指定的ID值爲38,換算成16進製爲0x26,則最後的key_t返回值爲0x2610002。 semid=semget(key,1,IPC_CREAT|0666);//建立並獲得信號量id if(semid==-1){ perror("semget"); exit(1); } printf("my semid is %d \n",semid); struct sembuf sbuf={0,-1,IPC_NOWAIT};// 上面sembuf結構體介紹中說,當sem_op=負數,請求sem_op的絕對值的資源。若是相應的資源數能夠知足請求,則將該信號量的值減去sem_op的絕對值,函數成功返回。當相應的資源數不能知足請求時,這個操做與sem_flg有關。sem_flg指定IPC_NOWAIT,則semop函數出錯返回EAGAIN。 union semun semopts; semopts.val=5; //對val賦值 if((semctl(semid,0,SETVAL,semopts))==-1){ // SETVAL就是給semun.val賦值的動做 perror("semctl"); exit(1); } printf("%s\n","ke" ); while(1){ if(semop(semid,&sbuf,1)==-1) // 這個操做就是semop來對{0,-1,IPC_NOWAIT}對應的動做 不斷-1,直到=0 exit(1); sleep(3); } return 0; }
#include <stdio.h> #include <stdlib.h> #include <sys/ipc.h> #include <sys/types.h> #include <sys/sem.h> int main(int argc, char const *argv[]) { int semid,semval; key_t key; key=ftok(".",3); //必須仍然用這兩個值計算,否則信號量對應不起來,固然前提是兩個代碼位於相同的路徑下 semid=semget(key,1,IPC_CREAT|0666); if(semid==-1){ perror("semget"); exit(1); } int val; while(1){ if((semval=semctl(semid,0,GETVAL,0))==-1)//GETVAL獲得semun.val值 exit(1); if(semval>0) printf("val is %d\n",semval); else{ printf("stop!\n"); break; } sleep(3); } return 0; }結果:
val is 4 val is 3 val is 2 val is 1 stop!兩個進程確實通訊成功。