Linux IPC实践(12) --System V信号量(2)
生活随笔
收集整理的這篇文章主要介紹了
Linux IPC实践(12) --System V信号量(2)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
實踐1:信號量實現進程互斥
父子進程執行流程如下:
父進程 | 子進程 |
P | P |
O(print) | X(print) |
sleep | sleep |
O(print) | X(print) |
V | V |
sleep | sleep |
從圖中可以看出,?O或X總是成對出現的,?要么兩個O,?要么兩個X;
/**P,V原語實現父子進程互斥使用終端**/ // 程序代碼 int main(int argc,char *argv[]) {int semid = sem_create(IPC_PRIVATE);sem_setval(semid, 1);int count = 10;pid_t pid = fork();if (pid == -1)err_exit("fork error");else if (pid > 0) //子進程{srand(getpid());while (count --){sem_P(semid);//臨界區開始cout << 'X';fflush(stdout); //一定要加上ffflush, 因為中斷是行緩沖的sleep(rand()%3);cout << 'X';fflush(stdout);//臨界區結束sem_V(semid);sleep(rand()%3);}}else //父進程{srand(getpid());while (count --){sem_P(semid);//臨界區開始cout << 'O';fflush(stdout);sleep(rand()%3);cout << 'O';fflush(stdout);//臨界區結束sem_V(semid);sleep(rand()%3);}wait(NULL);sem_delete(semid);}return 0; }實踐2:?信號量集解決哲學家進餐問題
? ?假設有五位哲學家圍坐在一張圓形餐桌旁,做以下兩件事情之一:吃飯,或者思考。吃東西的時候,他們就停止思考,思考的時候也停止吃東西。每兩個哲學家之間有一只餐叉。因為用一只餐叉很難吃飯,所以假設哲學家必須用兩只餐叉吃東西,?而且他們只能使用自己左右手邊的那兩只餐叉。
/** 解決的方法采用的是: 只有左右兩個刀叉都能夠使用時,才拿起兩個刀叉 實現了有死鎖和無死鎖的兩種形式的wait_2fork(見下) **/int semid; //沒有死鎖的wait void wait_2fork(unsigned short no) {unsigned short left = no;unsigned short right = (no+1)%5;struct sembuf sops[2] = {{left, -1, 0}, {right, -1, 0}};//同時獲取左右兩把刀叉if (semop(semid, sops, 2) == -1)err_exit("wait_2fork error"); } /* //有死鎖的wait void wait_2fork(unsigned short no) {unsigned short left = no;unsigned short right = (no+1)%5;struct sembuf sops = {left, -1, 0};//獲取左邊的刀叉if (semop(semid, &sops, 1) == -1)err_exit("wait_2fork error");sleep(4); //沉睡幾秒, 加速死鎖的產生sops.sem_num = right;//獲取右邊的刀叉if (semop(semid, &sops, 1) == -1)err_exit("wait_2fork error"); } */ //釋放兩把刀叉 void signal_2fork(unsigned short no) {unsigned short left = no;unsigned short right = (no+1)%5;struct sembuf sops[2] = {{left, 1, 0}, {right, 1, 0}};if (semop(semid, sops, 2) == -1)err_exit("signal_2fork error"); } //哲學家 void philosopher(unsigned short no) {srand(time(NULL));while (true){cout << no << " is thinking" << endl;sleep(rand()%5+1);cout << no << " is hunger" << endl;wait_2fork(no); //獲取兩把刀叉//進餐cout << "++ " << no << " is eating" << endl;sleep(rand()%5+1);signal_2fork(no);//釋放兩把刀叉} } int main() {// 創建一個信號量集: 里面包含5個信號量semid = semget(IPC_PRIVATE, 5, IPC_CREAT|0666);if (semid == -1)err_exit("semget error");//將每個信號量都設初值為1union semun su;su.val = 1;for (int i = 0; i < 5; ++i)if (semctl(semid, i, SETVAL, su) == -1)err_exit("semctl SETVAL error");//創建四個子進程, 將每個進程的編號設定為nopid_t pid;unsigned short no = 0;for (unsigned short i = 0; i < 4; ++i){pid = fork();if (pid == -1)err_exit("fork error");else if (pid == 0){no = i+1;break;}}// 最后五個進程(4個子進程+1個父進程)都會匯集到此處,// 每個進程代表著一個哲學家,編號no: 0~4philosopher(no);return 0; }新人創作打卡挑戰賽發博客就能抽獎!定制產品紅包拿不停!
總結
以上是生活随笔為你收集整理的Linux IPC实践(12) --System V信号量(2)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Zernike函数拟合曲面--MATLA
- 下一篇: Linux多线程实践(7) --多线程排