Linux环境编程之同步(四):Posix信号量
信號量是一種用于提供不同進程間或一個給定進程的不同線程間同步手段的原語。有三種類型:Posix有名信號量,使用Posix IPC名字標識。Posix基于內存的信號量,存放在共享內存區中;System V信號量。在內核中維護。
這三種信號量都可用于進程間或線程間的同步。
圖1 由兩個進程使用的一個二值信號量
圖2 由兩個進程使用的一個Posix有名二值信號量
圖3 由一個進程內的兩個線程共享的基于內存的信號量
一個進程可以在某個信號量上運行的三種操作:
1、創建一個信號量,這要求調用者指定初始值,對于二值信號量來說。它一般是1,也但是0。
2、等待一個信號量,該操作會測試這個信號量的值。假設小于0,就堵塞。也稱為P操作。
3、掛出一個信號量。該操作將信號量的值加1,也稱為V操作。
信號量、相互排斥鎖和條件變量之間的三個差異:
1、相互排斥鎖必須總是給它上鎖的線程解鎖,信號量的掛出卻不必由運行過它的等待操作的同一線程運行。
2、相互排斥鎖要么被鎖住,要么被解開。
3、既然信號量有一個與之關聯的狀態。那么信號量掛出操作總是被記住。
然而當向一個條件變量發送信號時。假設沒有線程等待在該條件變量上。信號丟失。
Posix提供兩類信號量:有名信號量和基于內存的信號量(也稱無名信號量)。
使用函數例如以下:
*/
semcreate程序: #include <semaphore.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h>#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)int main(int argc, char **argv) {int c, flags;sem_t *sem;unsigned int value;flags = O_RDWR | O_CREAT;value = 1;while((c = getopt(argc, argv, "ei:")) != -1){switch(c){case 'e':flags |= O_EXCL;case 'i':value = atoi(optarg);break; } }if(optind != argc - 1){printf("usage:semcreate [-e] [-i initalvalue] <name>\n"); return -1;}sem = sem_open(argv[optind], flags, FILE_MODE, value);sem_close(sem);exit(0); }semunlink程序: #include <semaphore.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h>int main(int argc, char **argv) {if(argc != 2){printf("usage:semunlink <name>.\n"); return -1;}sem_unlink(argv[1]);exit(0); }semgetvalue程序: #include <semaphore.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h>int main(int argc, char **argv) {sem_t *sem;int val;if(argc != 2){printf("usage:semgetvalue <name>.\n"); return -1;}sem = sem_open(argv[1], 0);sem_getvalue(sem, &val);printf("value = %d\n", val);exit(0); } semwait程序: #include <semaphore.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h>int main(int argc, char **argv) {sem_t *sem;int val;if(argc != 2){printf("usage: semwait <name>"); return -1;}sem = sem_open(argv[1], 0);sem_wait(sem);sem_getvalue(sem, &val);printf("pid %ld has semaphore, value = %d\n", (long)getpid(), val);pause(); /*block until killed*/exit(0); }sempost程序: #include <semaphore.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h>int main(int argc, char **argv) {sem_t *sem;int val;if(argc != 2){printf("usage:sempost <name>\n"); return -1;}sem = sem_open(argv[1], 0);sem_post(sem);sem_getvalue(sem, &val);printf("value = %d\n", val);exit(0); }Posix基于內存的信號量,由應用程序分配信號量的內存空間(也就是分配一個sem_t數據類型的內存空間),然后由系統初始化它們的值。#include <stmaphore.h> int sem_init(sem_t *sem, int shared, unsigned int value); /*出錯返回-1*/ int sem_destroy(sem_t *sem); <span style="white-space:pre"> </span>/*成功返回0,出錯返回-1*/基于內存的信號量是由sem_init初始化的,sem參數指向應用程序必須分配的sem_t變量。假設shared為0,那么待初始化的信號量是在同一進程的各個線程間共享的,否則該信號量是在進程間共享的。
當不須要使用與有名信號量關聯的名字時,可改用基于內存的信號量。
彼此無親緣關系的不同進程須要使用信號量時,通常使用有名信號量。其名字就是各個進程標識信號量的手段。基于內存信號量至少具有進程持續性,然而它們真正的持續性卻取決于存放信號量的內存區的類型。
僅僅要含有某個基于內存信號量的內存區保持有效,該信號量就一直存在。
進程間共享信號量
進程間共享基于內存信號量的規則非常easy:信號量本身必須駐留在由全部希望共享它的進程所共享的內存區中,并且sem_init的第二個參數必須是1。
有名信號量,不同進程總是可以訪問同一個有名信號量。僅僅要它們在調用sem_open時指定同樣的名字就可以。
信號量限制
Posix定義了兩個信號量限制:
SEM_NSEMS_MAX 一個進程可同一時候打開著的最大信號數
SEM_VALUE_MAX 一個信號量的最大值
這兩個常值定義在<unistd.h>頭文件里。可在運行時通過sysconf函數獲取。
轉載于:https://www.cnblogs.com/xfgnongmin/p/10651200.html
總結
以上是生活随笔為你收集整理的Linux环境编程之同步(四):Posix信号量的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Elasticsearch之如何合理分配
- 下一篇: linux-安装jdk