日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux进程间通信五 Posix 信号量简介与示例

發布時間:2025/4/5 linux 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux进程间通信五 Posix 信号量简介与示例 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 信號量簡介

信號量用于進程或線程間同步,Posix信號量是一個非負整型,只有兩種操作,加一(sem_post)和減一(sem_wait),如果信號量值為0,sem_wait默認阻塞。

Posix信號量有兩種,有名信號量和無名信號量,顧名思義,就是是否有名字。有名信號量有一個名字,長度不超過NAME_MAX-4(i.e. 251),因為內核會默認加上'sem.',所以這里要減4,名字以斜杠開頭'/',后面跟上一個或多個非斜杠字符。不同進程可以通過同一個名字來操作有名信號量,sem_open用于創建或者獲取已存在的信號量,創建好之后就可以使用sem_post或者sem_wait來操作。使用完之后可以使用sem_close來關閉信號量,sem_unlink用來刪除信號量,刪除并不立即銷毀,只有當所有進程都sem_close才開始銷毀。

無名信號量沒有名字,基于內存,通常用在同一個進程線程之間或者不同進程的共享內存里,因為同一個進程的不同線程共享進程地址空間,所以可以訪問到,放到共享內存里也可以被不同進程訪問到。使用前必須使用sem_init進行初始化,初始化之后就可以使用sem_waitsem_post操作,使用完成后sem_destroy接口進行銷毀,下一節介紹接口的使用

2. 信號量API接口

2.1 有名信號量創建

#include <fcntl.h> /* For O_* constants */ #include <sys/stat.h> /* For mode constants */ #include <semaphore.h>/** * @brief 創建或獲取有名信號量 * * @params name 有名信號量關聯的名字,斜杠開頭,長度不超過NAME_MAX-4(e.g. 251) * @params oflag 標志位,可選值包括O_CREAT| O_EXCL * 這里如果指定了O_CREAT標志位,還要填寫額外兩個參數,mode和value * * @params mode,參考open函數,通常填0即可 * @params value 信號量的初始值 * @returns 成功返回描述符,失敗返回-1 **/sem_t *sem_open(const char *name, int oflag); sem_t *sem_open(const char *name, int oflag,mode_t mode, unsigned int value);# 編譯加上 -pthread選項 Link with -pthread.

2.2 信號量減一操作

#include <semaphore.h>/** * @brief lock信號量并減1,當信號量大于0,操作可以執行,否則則阻塞。如果設置了NONBLOCK標志位,則報錯返回 * * @params sem 信號量描述符 * @returns 成功返回0,失敗返回-1 **/ int sem_wait(sem_t *sem);/** * @brief 同sem_wait,只不過如果無法減1則立即報錯返回 * **/ int sem_trywait(sem_t *sem);/** * @brief 同sem_wait,只不過如果無法減1則會等待一段時間,注意這里時間參數要設置正確 * **/ int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);# 編譯鏈接選項 -pthread Link with -pthread.

2.3 信號量加1操作

#include <semaphore.h>/** * @brief 信號量的值加1 * * @params sem 信號量文件描述符 * @returns 成功返回0,失敗返回-1 **/int sem_post(sem_t *sem);# 編譯鏈接選項 -pthread Link with -pthread.

2.4 關閉有名信號量

#include <semaphore.h>/** * @brief 關閉信號量,系統為當前進程分配的信號量資源會被釋放。 * * @params sem 信號量文件描述符 * @returns 成功返回0,失敗返回-1 **/int sem_close(sem_t *sem);# 編譯鏈接選項 -pthread Link with -pthread.

2.5 銷毀有名信號量

#include <semaphore.h>/** * @brief 銷毀信號量,只有當所有進程都關閉信號量之后才開始銷毀工作 * * @params name 信號量名字 * @returns 成功返回0,失敗返回-1 **/int sem_unlink(const char *name);# 編譯鏈接選項 -pthread Link with -pthread.

2.6 初始化無名信號量

#include <semaphore.h>/** * @brief 初始化無名信號量 * * @params sem 待初始化的信號量地址 * @params pshared 為0表示線程間共享,非0表示進程間共享 * @params value 信號量初始值,不超過SEM_VALUE_MAX * @returns 成功返回0,失敗返回-1 **/int sem_init(sem_t *sem, int pshared, unsigned int value);# 編譯鏈接選項 -pthread Link with -pthread.

2.7 銷毀無名信號量

#include <semaphore.h>/** * @brief 銷毀無名信號量 * * @params sem 要銷毀的信號量 * 如果有其它線程或進程阻塞在sem上,此時銷毀會產生未定義的行為 * * @returns 成功返回0,失敗返回-1 **/int sem_destroy(sem_t *sem);# 編譯鏈接選項 -pthread Link with -pthread.

3 有名信號量例子

3.1 信號量生產者

// 生產者 #include <fcntl.h> /* For O_* constants */ #include <sys/stat.h> /* For mode constants */ #include <semaphore.h> #include <errno.h> #include <stdlib.h> #include <unistd.h> #include <stdio.h>#define SEM_NAME "/sem0"int main(int argc, char** argv) {if (argc < 3){printf("Usage: ./sem_post timeval nums\n");return -1;}int ts = atoi(argv[1]);int total = atoi(argv[2]);if (total < 1 || ts < 1){printf("invalid param\n");return -1;}sem_t* sem_id;// 創建信號量并初始化值為0sem_id = sem_open(SEM_NAME, O_CREAT, O_RDWR, 0);if (sem_id == SEM_FAILED){perror("sem_open error");return -1;}int curr = 0;while (curr < total){ // 生成信號量,即加1while (sem_post(sem_id)){perror("sem_post error, try later");sleep(1);}printf("producing succ\n");sleep(ts);++curr;}printf("work done\n");// 關閉信號量sem_close(sem_id);return 0; }

3.2 信號量消費者

// 消費者 #include <fcntl.h> /* For O_* constants */ #include <sys/stat.h> /* For mode constants */ #include <semaphore.h> #include <errno.h> #include <stdlib.h> #include <unistd.h> #include <stdio.h>#define SEM_NAME "/sem0"int main() {sem_t* sem_id;// 創建信號量并初始化值為0sem_id = sem_open(SEM_NAME, O_CREAT, O_RDWR, 0);if (sem_id == SEM_FAILED){perror("sem_open error");return -1;}while (1){// 消費信號量if (sem_wait(sem_id)){perror("sem_wait fail, try later\n");sleep(1);continue;}printf("consuming succ\n");}// 關閉信號量sem_close(sem_id);return 0; }

3.3 編譯&運行

default:gcc -o sem_post sem_post.c -pthreadgcc -o sem_wait sem_wait.c -pthread clean:rm -rf sem_wait sem_post

?

4. 無名信號量例子

創建兩個線程,分別用于生產和消費

#include <semaphore.h> #include <pthread.h> #include <stdio.h> #include <stdlib.h>// 消費者 void* consumer_worker(void *arg) {sem_t *sem = arg;while (1){// 消費信號量if (sem_wait(sem)){perror("[consumer] sem_wait error, try later\n");sleep(1);continue;}printf("[consumer] consume succ\n");}return 0; }// 生產者 void* producer_worker(void *arg) {sem_t *sem = arg;while (1){// 生成信號量if (sem_post(sem)){perror("[producer] sem_post error, try later\n");sleep(1);continue;}printf("[producer] produce succ\n");sleep(1);}return 0; }int main(int argc, char** argv) {pthread_t consumer, producer;if (argc < 2){printf("Usage: ./unnamed_sem time\n");return -1;}int tm = atoi(argv[1]);if (tm < 1){printf("invalid param\n");return -1;}sem_t sem;// 無名信號量初始化if (sem_init(&sem, 0, 0)){perror("sem_init error");return -1;}// 創建生產者線程if (pthread_create(&producer, NULL, &producer_worker, (void *)&sem)){perror("create producer_worker error");sem_destroy(&sem);return -1;}// 創建消費者線程if (pthread_create(&consumer, NULL, &consumer_worker, (void *)&sem)){perror("create consumer_worker error");sem_destroy(&sem);return -1;}printf("main thread sleep:%d\n", tm);sleep(tm);// 無名信號量銷毀sem_destroy(&sem);return 0; }

5. 參考資料

1.?https://www.man7.org/linux/man-pages/man7/sem_overview.7.html

2. 《Linux環境編程 從應用到內核》?

================================================================================================

Linux應用程序、內核、驅動、后臺開發交流討論群(745510310),感興趣的同學可以加群討論、交流、資料查找等,前進的道路上,你不是一個人奧^_^。

總結

以上是生活随笔為你收集整理的Linux进程间通信五 Posix 信号量简介与示例的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。