Linux之訊號量
阿新 • • 發佈:2018-12-10
訊號量概念
Dijkstra提出的“訊號量”概念是共發程式設計領域的一項重大進步 訊號量是一種變數,它只能取正整數值,對這些正整數只能進行兩種操作:等待和訊號 用兩種記號來表示訊號量的這兩種操作: P(semaphore variable) 代表等待 V(semaphore variable) 代表訊號
訊號量操作
首先我們對訊號量進行封裝:
//錯誤列印 void error_exit(char *errorinfo) { printf("%s\n",errorinfo); exit(EXIT_FAILURE); } //訊號量建立 int sem_create(key_t key,int nsems) { int semid = semget(key,nsems,IPC_CREAT|0766); if(semid <0) { error_exit("creat sem error"); } return semid; } //訊號量的開啟 int sem_myopen(key_t key) { int semid = semget(key,0,0); if(semid <0) { error_exit("creat sem error"); } return semid; } //訊號量刪除 int sem_delete(int semid) { int ret = semctl(semid,0,IPC_RMID); if(ret<0) { error_exit("delete sem error"); } return ret; } //訊號量設定裡面的值 int sem_setval(int semid,int nsempos,int val) { union semun arg; arg.val=val; int ret=semctl(semid,nsempos,SETVAL,arg); if(ret<0) { error_exit("set value error"); } return ret; } //訊號量獲取裡面的值 int sem_getval(int semid,int nsempos) { int value=semctl(semid,nsempos,GETVAL); if(value<0) { error_exit("get value error"); } return value; } //訊號量設定 int sem_setall(int semid,unsigned short*values) { union semun arg; arg.array=values; int ret=semctl(semid,0,SETVAL,values); if(ret<0) { error_exit("set all error"); } return ret; } //訊號量獲取 int sem_getall(int semid,unsigned short*values) { union semun arg; arg.array=values; int ret=semctl(semid,0,GETVAL,values); if(ret<0) { error_exit("set all error"); } return ret; } //訊號量V操作 int sem_v(int semid,int npos) { struct sembuf buf={npos,1,0}; int ret=semop(semid,&buf,1); if (ret<0) { error_exit("sem p error"); } return ret; } //訊號量P操作 int sem_p(int semid,int npos) { struct sembuf buf={npos,-1,0}; int ret=semop(semid,&buf,1); if (ret<0) { error_exit("sem p error"); } return ret; }
簡單使用上面封裝的函式實現 父子程序上鎖
int main() { int semid= sem_create((key_t)0002,1); sem_setval(semid,0,0); int pid =fork(); //父程序 if(pid>0) { while(1) { printf("parent working\n"); sleep(5); sem_v(semid,0); } } //子程序 else if(pid==0) { while(1) { printf("child wait\n"); sem_p(semid,0); printf("child working\n"); } } else { perror("fork error\n"); } return 0; }
實現結果:(每次執行完一個程序才會執行下一個程序,可用於兩程序協同處理事情的時候進行使用)
使用以上封裝的函式實現多程序p和v的操作
int main() { int semid=sem_create((key_t)0001,1); sem_setval(semid,0,10); fork(); fork(); fork(); fork(); fork(); fork(); sleep(1); printf("my name is %d\n",getpid()); sem_p(semid,0); printf("%d get\n",getpid()); sleep(5); printf("%d done\n",getpid()); sem_v(semid,0); return 0; }
結果:
上面結果:fork6次,總共64個程序,如同64個人練車一樣,但是隻有10輛車(set_value的第三個引數設定了10),使用p操作代表車被用了一輛,v代表車使用完讓出來給別人用,這就是生產者和消費者模型,進行資源保護