Linux环境编程之同步(四):Posix信号量
信號(hào)量是一種用于提供不同進(jìn)程間或一個(gè)給定進(jìn)程的不同線程間同步手段的原語。有三種類型:Posix有名信號(hào)量,使用Posix IPC名字標(biāo)識(shí)。Posix基于內(nèi)存的信號(hào)量,存放在共享內(nèi)存區(qū)中;System V信號(hào)量。在內(nèi)核中維護(hù)。
這三種信號(hào)量都可用于進(jìn)程間或線程間的同步。
圖1 由兩個(gè)進(jìn)程使用的一個(gè)二值信號(hào)量
圖2 由兩個(gè)進(jìn)程使用的一個(gè)Posix有名二值信號(hào)量
圖3 由一個(gè)進(jìn)程內(nèi)的兩個(gè)線程共享的基于內(nèi)存的信號(hào)量
一個(gè)進(jìn)程可以在某個(gè)信號(hào)量上運(yùn)行的三種操作:
1、創(chuàng)建一個(gè)信號(hào)量,這要求調(diào)用者指定初始值,對(duì)于二值信號(hào)量來說。它一般是1,也但是0。
2、等待一個(gè)信號(hào)量,該操作會(huì)測(cè)試這個(gè)信號(hào)量的值。假設(shè)小于0,就堵塞。也稱為P操作。
3、掛出一個(gè)信號(hào)量。該操作將信號(hào)量的值加1,也稱為V操作。
信號(hào)量、相互排斥鎖和條件變量之間的三個(gè)差異:
1、相互排斥鎖必須總是給它上鎖的線程解鎖,信號(hào)量的掛出卻不必由運(yùn)行過它的等待操作的同一線程運(yùn)行。
2、相互排斥鎖要么被鎖住,要么被解開。
3、既然信號(hào)量有一個(gè)與之關(guān)聯(lián)的狀態(tài)。那么信號(hào)量掛出操作總是被記住。
然而當(dāng)向一個(gè)條件變量發(fā)送信號(hào)時(shí)。假設(shè)沒有線程等待在該條件變量上。信號(hào)丟失。
Posix提供兩類信號(hào)量:有名信號(hào)量和基于內(nèi)存的信號(hào)量(也稱無名信號(hào)量)。
使用函數(shù)例如以下:
*/
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基于內(nèi)存的信號(hào)量,由應(yīng)用程序分配信號(hào)量的內(nèi)存空間(也就是分配一個(gè)sem_t數(shù)據(jù)類型的內(nèi)存空間),然后由系統(tǒng)初始化它們的值。#include <stmaphore.h> int sem_init(sem_t *sem, int shared, unsigned int value); /*出錯(cuò)返回-1*/ int sem_destroy(sem_t *sem); <span style="white-space:pre"> </span>/*成功返回0,出錯(cuò)返回-1*/基于內(nèi)存的信號(hào)量是由sem_init初始化的,sem參數(shù)指向應(yīng)用程序必須分配的sem_t變量。假設(shè)shared為0,那么待初始化的信號(hào)量是在同一進(jìn)程的各個(gè)線程間共享的,否則該信號(hào)量是在進(jìn)程間共享的。
當(dāng)不須要使用與有名信號(hào)量關(guān)聯(lián)的名字時(shí),可改用基于內(nèi)存的信號(hào)量。
彼此無親緣關(guān)系的不同進(jìn)程須要使用信號(hào)量時(shí),通常使用有名信號(hào)量。其名字就是各個(gè)進(jìn)程標(biāo)識(shí)信號(hào)量的手段。基于內(nèi)存信號(hào)量至少具有進(jìn)程持續(xù)性,然而它們真正的持續(xù)性卻取決于存放信號(hào)量的內(nèi)存區(qū)的類型。
僅僅要含有某個(gè)基于內(nèi)存信號(hào)量的內(nèi)存區(qū)保持有效,該信號(hào)量就一直存在。
進(jìn)程間共享信號(hào)量
進(jìn)程間共享基于內(nèi)存信號(hào)量的規(guī)則非常easy:信號(hào)量本身必須駐留在由全部希望共享它的進(jìn)程所共享的內(nèi)存區(qū)中,并且sem_init的第二個(gè)參數(shù)必須是1。
有名信號(hào)量,不同進(jìn)程總是可以訪問同一個(gè)有名信號(hào)量。僅僅要它們?cè)谡{(diào)用sem_open時(shí)指定同樣的名字就可以。
信號(hào)量限制
Posix定義了兩個(gè)信號(hào)量限制:
SEM_NSEMS_MAX 一個(gè)進(jìn)程可同一時(shí)候打開著的最大信號(hào)數(shù)
SEM_VALUE_MAX 一個(gè)信號(hào)量的最大值
這兩個(gè)常值定義在<unistd.h>頭文件里。可在運(yùn)行時(shí)通過sysconf函數(shù)獲取。
轉(zhuǎn)載于:https://www.cnblogs.com/xfgnongmin/p/10651200.html
總結(jié)
以上是生活随笔為你收集整理的Linux环境编程之同步(四):Posix信号量的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Elasticsearch之如何合理分配
- 下一篇: linux-安装jdk