linux进程间通信:POSIX信号量
生活随笔
收集整理的這篇文章主要介紹了
linux进程间通信:POSIX信号量
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 概念描述
- 編程接口
- 注意事項
- 編程案例
- 信號量基本接口使用案例
- 信號量父子進程間通信
- 信號量實現 兩進程之間通信
概念描述
- 英文:
semaphore簡稱SEM,主要用來進行進程間同步 - 本質:內核維護的一個正整數,可對其進行各種+/-操作
- 分類:systemV 信號量、POSIX 有名信號量、POSIX 無名信號量
- 用途:用來標示系統中可用資源的的個數,協調各個進程有序的訪問資源,防止發生沖突
- P操作:程序在進入臨界區之前要對資源進行申請,對資源的引用計數要-1,當資源個數為0時進程p操作會發生阻塞
- V操作:程序離開臨界區后要釋放相應的資源,對資源對引用計數要+1
編程接口
以下接口編碼過程中都可以通過man sem_open這種方式查看接口對具體使用方式,詳細信息則不列舉
sem_t *sem_open(const char *name, int oflag); //使用字符串創建一個信號量
sem_t *sem_open(const char *name, int oflag,mode_t mode, unsigned int value); //使用字符串創一個一個信號量,并初始化信號量的值
int sem_close(sem_t *sem);
int sem_post(sem_t *sem); //信號量的v操作 +1
int sem_wait(sem_t *sem); //信號量的p操作 -1
int sem_trywait(sem_t *sem); //信號量進行p操作,但是值已經為0,此時會立即返回錯而非阻塞//信號量進行p操作,如信號量的值為0,則阻塞abs_timeout結構體中的時間內還是無法執行p操作,則返回錯誤
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
int sem_unlink(const char *name);//刪除名稱為name的信號量
int sem_getvalue(sem_t *sem, int *sval);//獲取信號量sem所代表的value數值
注意事項
- 以上編程接口包含頭文件:
#include <semaphore.h> - 編譯時需指定:
-lpthread進行編譯
編程案例
linux系統中創建的信號量存放路徑為/dev/shm
信號量基本接口使用案例
sem_demo.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <fcntl.h>int main (){//創建信號量并初始化信號量的value值為4unsigned int sem_value = 4;sem_t *sem = sem_open("posix_sem", O_RDWR | O_CREAT,0777,sem_value);if (sem == SEM_FAILED) {printf("sem_open failed\n");_exit(-1);}//獲取信號量的value值if (sem_getvalue(sem,&sem_value) != -1) {printf("sem_getvalue is %d\n",sem_value);}//對信號量進行p(-1)操作sem_wait(sem);sem_wait(sem);sem_wait(sem);sem_wait(sem);//sem_trywait(sem);//并不會發生阻塞,此時sem值已經為0,無法再進行p操作if(sem_getvalue(sem,&sem_value) != -1) {printf("sem_getvalue after sem_wait is %d\n",sem_value);}//對信號量進行v(+1)操作sem_post(sem);sem_post(sem);sem_post(sem);sem_post(sem);if(sem_getvalue(sem,&sem_value) != -1) {printf("sem_getvalue after sem_post is %d\n",sem_value);}if(sem_close(sem) != -1) {printf("sem_close success\n");}printf("wait for unlink sem\n");sleep(10);//刪除名稱為posix_sem信號量if(sem_unlink("posix_sem") != -1) {printf("sem_unlink success \n");}return 0;
}
編譯gcc sem_demo.c -lpthread 輸出如下:
sem_getvalue is 4
sem_getvalue after sem_wait is 0
sem_getvalue after sem_post is 4
sem_close success
wait for unlink sem
sem_unlink success
同時在等待10秒刪除期間我們查看/dev/shm目錄下的sem文件存在,當10秒過后sem文件則被刪除
信號量父子進程間通信
sem_comu.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <fcntl.h>#define SEM_NAME "posix_sem_comu"int main (){int i = 0, j = 0,sem_val = 0,ret;sem_t *sem;sem = sem_open(SEM_NAME, O_CREAT,0666,1);ret = fork();if (ret == -1) {printf("sem_open failed \n");sem_close(sem);sem_unlink(SEM_NAME);_exit(-1);}//創建的子進程,執行10次p操作,每次間隔1秒else if(ret == 0) {while (i++ <= 10) {sem_wait(sem);if (sem_getvalue(sem,&sem_val) != -1) {printf("child process :sem value is %d\n",sem_val);sleep(1);}}_exit(1);}//父進程執行10次v操作,每次間隔兩秒else {while (j++ <=10) {sem_post(sem);if (sem_getvalue(sem,&sem_val) != -1) {printf("prarent process :sem value is %d\n",sem_val);sleep(2);}}}//最終刪除sem信號量sem_close(sem);if (sem_unlink(SEM_NAME) != -1) {printf("sem_unlink success \n");}return 0;
}
編譯:gcc sem_comu.c -o comu -lpthread
輸出如下,可以很明顯的看到子即使子進程的p操作頻率快于父進程v操作,但是對同一信號量,他們仍然能夠有序同步訪問。因為子進程p操作頻率較快,此時信號量的value會很快減為0,子進程此時再進行p操作會發生阻塞;直到父進程執行v操作將信號量的值變為1子進程才能繼續訪問
prarent process :sem value is 2
child process :sem value is 1
child process :sem value is 0
prarent process :sem value is 1
child process :sem value is 0
prarent process :sem value is 1
child process :sem value is 0
prarent process :sem value is 1
child process :sem value is 0
prarent process :sem value is 1
child process :sem value is 0
prarent process :sem value is 1
child process :sem value is 0
prarent process :sem value is 1
child process :sem value is 0
prarent process :sem value is 1
child process :sem value is 0
prarent process :sem value is 1
child process :sem value is 0
prarent process :sem value is 1
child process :sem value is 0
prarent process :sem value is 1
sem_unlink success
信號量實現 兩進程之間通信
兩個進程,使用同一個信號量共同訪問一個臨界區,利用信號量的pv操作,實現同步訪問
sem_post.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <fcntl.h>int main(){char *name = "/posix_sem";int j = 0, sem_value = 4;sem_t *sem;sem = sem_open(name, O_CREAT, 0666, sem_value);if (sem == SEM_FAILED) {printf("sem open failed \n");_exit(-1);}printf("sem_open %s success \n",name);//對信號量進行5次 v操作,每次間隔5秒while(j++ <= 10) {if(sem_post(sem) == -1) {printf("sem _posd failed\n");_exit(-1);}if(sem_getvalue(sem,&sem_value) != -1) {printf("sem post success %d\n",sem_value);}sleep(5);}sleep(10);if(sem_close(sem) != -1) {printf("sem_close success \n");}if (sem_unlink(name) != -1) {printf("sem_unlink success \n");}return 0;
}
sem_wait.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <fcntl.h>int main(){char *name = "/posix_sem";int j = 0, sem_value = 4;sem_t *sem;sem = sem_open(name, O_CREAT, 0666, sem_value);if (sem == SEM_FAILED) {printf("sem open failed \n");_exit(-1);}printf("sem_open %s success \n",name);//對信號量進行p操作,每次間隔5秒,總共進行10次while(j++ <= 10) {if(sem_post(sem) == -1) {printf("sem _posd failed\n");_exit(-1);}if(sem_getvalue(sem,&sem_value) != -1) {printf("sem post success %d\n",sem_value);}sleep(5);}//執行結束后關閉信號量,并刪除信名稱為name的信號量sleep(10);if(sem_close(sem) != -1) {printf("sem_close success \n");}if (sem_unlink(name) != -1) {printf("sem_unlink success \n");}return 0;
}
編譯:
gcc sem_post.c -o post -lpthread
gcc sem_wait.c -o wait -lpthread
可以看到輸出如下,兩進程是能夠正常進行信號量value值的訪問同步
總結
以上是生活随笔為你收集整理的linux进程间通信:POSIX信号量的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux进程间通信:POSIX 消息队
- 下一篇: 肩并着肩是哪首歌啊?