Linux进程通信之信号量
文章目錄
- 1 簡(jiǎn)介
- 2 Posix信號(hào)量
- 2.1 有名信號(hào)量
- 2.2 無(wú)名信號(hào)量
- 2.3 例程變種
- 2.3.1 多生產(chǎn)者單消費(fèi)者
- 2.3.2 多生產(chǎn)者多消費(fèi)者
- 2.3.3 多緩沖讀取
- 3 System V信號(hào)量
- 3.1 System V信號(hào)量
- 3.2 示例
1 簡(jiǎn)介
??信號(hào)量是用于提供不用進(jìn)程或者不同線(xiàn)程之間的同步手段的原語(yǔ),分為:
- Posix 有名信號(hào)量:可用于進(jìn)程或者線(xiàn)程間的同步;
- Posix基于內(nèi)存的信號(hào)量(無(wú)名信號(hào)量):存放于共享內(nèi)存中,可用于進(jìn)程或者線(xiàn)程的同步;
- System V信號(hào)量:在內(nèi)核中維護(hù),可用于進(jìn)程或線(xiàn)程間的同步。
??另外信號(hào)量同時(shí)根據(jù)取值不同可分為:
- 二值信號(hào)量:取值只能是0或者1,可以實(shí)現(xiàn)類(lèi)似互斥鎖的跨進(jìn)程的鎖機(jī)制。
- 計(jì)數(shù)信號(hào)量:取值大于1。
??計(jì)數(shù)信號(hào)量具備兩種操作動(dòng)作,稱(chēng)為V(signal())與P(wait())(即部分參考書(shū)常稱(chēng)的“PV操作”)。V操作會(huì)增加信號(hào)標(biāo)S的數(shù)值,P操作會(huì)減少它。
- P操作,檢測(cè)信標(biāo)值S:
- 如果S <= 0,則阻塞直到S > 0,并將信標(biāo)值S=S-1;
- 如果S > 0,則直接S=S-1;
- V操作:直接增加信標(biāo)值S=S+1。
??PV操作某種程度上等價(jià)于如下代碼只不過(guò)是原子的.
int p(int seq) {while(seq <= 0) ;return --seq; }int v(int seq) {return ++seq; }??互斥鎖,信號(hào)量和條件變量的區(qū)別:
2 Posix信號(hào)量
2.1 有名信號(hào)量
#include <semaphore.h> sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value); int sem_close(sem_t *sem); int sem_unlink(const char *name); int sem_post(sem_t *sem); int sem_wait(sem_t *sem); int sem_trywait(sem_t *sem); int sem_getvalue(sem_t *sem, int *sval);- sem_open:創(chuàng)建或者打開(kāi)一個(gè)信號(hào)量;
- name:信號(hào)量在文件系統(tǒng)上的文件名;
- oflag:可以為0,O_CREAT或者O_CREAT|O_EXCL;
- mode:信號(hào)量的權(quán)限位;
- value:信號(hào)量的初值不能大于SEM_VALUE_MAX;
- 返回自sem_t是一個(gè)該信號(hào)量的標(biāo)識(shí)符的指針;
- sem_close:關(guān)閉一個(gè)信號(hào)量,但是并不刪除信號(hào)量,另外進(jìn)程終止系統(tǒng)會(huì)自動(dòng)關(guān)閉當(dāng)前進(jìn)程打開(kāi)的信號(hào)量;
- sem:信號(hào)量的指針,通過(guò)sem_open獲得;
- sem_unlink:刪除信號(hào)量,需要注意的是信號(hào)量同樣維護(hù)了一個(gè)引用計(jì)數(shù),只有當(dāng)引用計(jì)數(shù)為0時(shí)才會(huì)顯示的刪除;
- name:信號(hào)量的在文件系統(tǒng)上的唯一標(biāo)示;
- sem_post:V操作,將信號(hào)量的值+1,并喚醒等待信號(hào)量的任意線(xiàn)程;
- sem:信號(hào)量的指針,通過(guò)sem_open獲得;
- sem_wait:P操作,如果當(dāng)前信號(hào)量小于等于0則阻塞,將信號(hào)量的值-1,否則直接將信號(hào)量-1;
- sem:信號(hào)量的指針,通過(guò)sem_open獲得;
- sem_trywait:非阻塞的sem_wait;
- sem:信號(hào)量的指針,通過(guò)sem_open獲得;
- sem_getvalue:獲取當(dāng)前信號(hào)量的值,如果當(dāng)前信號(hào)量上鎖則返回0或者負(fù)值,其絕對(duì)值為信號(hào)量的值;
- sem:信號(hào)量的指針,通過(guò)sem_open獲得;
- sval:信號(hào)量的值;
- 以上的函數(shù)除了sem_open失敗返回SEM_FAILED,均是成功返回0,失敗返回-1并且設(shè)置errno。
??簡(jiǎn)單的消費(fèi)者-生產(chǎn)者問(wèn)題:
#define BUFF_SIZE 5 typedef struct named_share {char buff[BUFF_SIZE];sem_t *lock;sem_t *nempty;sem_t *nstored;int items; }named_share;void* named_produce(void *arg) {named_share *ptr = arg;for(int i = 0;i < ptr->items;i++){lsem_wait(ptr->nempty);lsem_wait(ptr->lock); //鎖//生產(chǎn)物品ptr->buff[i % BUFF_SIZE] = rand() % 1000;printf("produce %04d into %2d\n", ptr->buff[i % BUFF_SIZE], i % BUFF_SIZE);sleep(rand()%2);lsem_post(ptr->lock); //解鎖lsem_post(ptr->nstored);}return NULL; }void* named_consume(void *arg) {named_share *ptr = arg;for(int i = 0;i < ptr->items;i++){lsem_wait(ptr->nstored);lsem_wait(ptr->lock); //鎖//生產(chǎn)物品printf("consume %04d at %2d\n", ptr->buff[i % BUFF_SIZE], i % BUFF_SIZE);ptr->buff[i % BUFF_SIZE] = -1;sleep(rand()%2);lsem_post(ptr->lock); //解鎖lsem_post(ptr->nempty);//iterator}return NULL; }void named_sem_test() {char *nempty_name = "nempty";char *nstored_name = "nstored";char *lock_name = "lock";int items = 10;int flag = O_CREAT | O_EXCL;named_share arg;srand(time(NULL));arg.items = items;memset(arg.buff, -1, sizeof(int) * BUFF_SIZE);arg.nempty = lsem_open(lpx_ipc_name(nempty_name), flag, FILE_MODE, BUFF_SIZE);arg.nstored = lsem_open(lpx_ipc_name(nstored_name), flag, FILE_MODE, 0);arg.lock = lsem_open(lpx_ipc_name(lock_name), flag, FILE_MODE, 1);pthread_t pid1, pid2;int val = 0;lsem_getvalue(arg.nstored, &val);lsem_getvalue(arg.nempty, &val);pthread_setconcurrency(2); lpthread_create(&pid1, NULL, named_produce, &arg);lpthread_create(&pid2, NULL, named_consume, &arg);lpthread_join(pid1, NULL);lpthread_join(pid2, NULL);lsem_unlink(lpx_ipc_name(nempty_name));lsem_unlink(lpx_ipc_name(nstored_name));lsem_unlink(lpx_ipc_name(lock_name)); }??結(jié)果:
? build git:(master) ? ./main produce 0038 into 0 produce 0022 into 1 produce 0049 into 2 produce 0060 into 3 produce 0090 into 4 consume 0038 at 0 consume 0022 at 1 consume 0049 at 2 consume 0060 at 3 consume 0090 at 4 produce 0031 into 0 produce -056 into 1 produce -103 into 2 produce -047 into 3 produce -100 into 4 consume 0031 at 0 consume -056 at 1 consume -103 at 2 consume -047 at 3 consume -100 at 42.2 無(wú)名信號(hào)量
int sem_init(sem_t *sem, int pshared, unsigned int value); int sem_destroy(sem_t *sem);- ```sem_init``:初始化一個(gè)無(wú)名信號(hào)量;
- sem:信號(hào)量的指針;
- pshared:標(biāo)志是否共享:
- pshared==0:該信號(hào)量只能在同一進(jìn)程不同線(xiàn)程之間共享,當(dāng)進(jìn)程終止則消失;
- pshared!=0:該信號(hào)量駐留與共享內(nèi)存區(qū),可以在不同進(jìn)程之間進(jìn)行共享;
- value:信號(hào)量的初值;
- 返回值出錯(cuò)返回-1,成功并不返回0;
- sem_destroy:銷(xiāo)毀信號(hào)量。成功返回0,失敗返回-1。
??上面的程序的簡(jiǎn)易修改:
void unnamed_sem_test() {int items = 10;named_share arg;srand(time(NULL));arg.items = items;memset(arg.buff, -1, sizeof(int) * BUFF_SIZE);arg.lock = (sem_t*)malloc(sizeof(sem_t));arg.nempty = (sem_t*)malloc(sizeof(sem_t));arg.nstored = (sem_t*)malloc(sizeof(sem_t));lsem_init(arg.lock, 0, 1);lsem_init(arg.nempty, 0, BUFF_SIZE);lsem_init(arg.nstored, 0, 0);pthread_t pid1, pid2;pthread_setconcurrency(2); lpthread_create(&pid1, NULL, named_produce, &arg);lpthread_create(&pid2, NULL, named_consume, &arg);lpthread_join(pid1, NULL);lpthread_join(pid2, NULL);lsem_destroy(arg.lock);lsem_destroy(arg.nempty);lsem_destroy(arg.nstored);SAFE_RELEASE(arg.lock);SAFE_RELEASE(arg.nempty);SAFE_RELEASE(arg.nstored); } ? build git:(master) ? ./main produce -120 into 0 produce -098 into 1 produce 0123 into 2 produce -058 into 3 produce 0028 into 4 consume -120 at 0 consume -098 at 1 consume 0123 at 2 consume -058 at 3 consume 0028 at 4 produce 0110 into 0 produce 0034 into 1 produce -068 into 2 produce -115 into 3 produce 0004 into 4 consume 0110 at 0 consume 0034 at 1 consume -068 at 2 consume -115 at 3 consume 0004 at 42.3 例程變種
2.3.1 多生產(chǎn)者單消費(fèi)者
??多生產(chǎn)者單消費(fèi)者需要關(guān)注的是不同生產(chǎn)者之間的進(jìn)度同步。
typedef struct multp_singc_share {int i;sem_t nempty;sem_t nstored;sem_t lock;int items;char buff[BUFF_SIZE]; }multp_singc_share;void* multp_singc_produce(void *arg) {multp_singc_share *ptr = arg;for(;;){lsem_wait(&(ptr->nempty));lsem_wait(&(ptr->lock));if(ptr->i >= ptr->items){lsem_post(&(ptr->lock));lsem_post(&(ptr->nempty));return NULL;}ptr->buff[ptr->i % BUFF_SIZE] = rand() % 100;printf("produce %d at %d\n", ptr->buff[ptr->i * BUFF_SIZE], ptr->i % BUFF_SIZE);ptr->i++;lsem_post(&ptr->lock);lsem_post(&ptr->nstored);} }void* multp_singc_consume(void *arg) {multp_singc_share *ptr = arg;for(int i = 0;i < ptr->items;i ++){lsem_wait(&(ptr->nstored));lsem_wait(&(ptr->lock));printf("consume %d at %d\n", ptr->buff[i % BUFF_SIZE], i % BUFF_SIZE);lsem_post(&(ptr->lock));lsem_post(&(ptr->nempty));} }void multp_singc_test() {multp_singc_share arg;pthread_t pro_th[THREAD_SIZE], con_th;arg.items = 10;arg.i = 0;memset(arg.buff, 0, BUFF_SIZE * sizeof(int));lsem_init(&(arg.lock), 0, 1);lsem_init(&(arg.nempty), 0, BUFF_SIZE);lsem_init(&(arg.nstored), 0, 0);pthread_setconcurrency(THREAD_SIZE + 1); for(int i = 0;i < THREAD_SIZE;i ++){lpthread_create(&pro_th[i], NULL, multp_singc_produce, &arg);}lpthread_create(&con_th, NULL, multp_singc_consume, &arg);for(int i = 0;i < THREAD_SIZE;i ++){lpthread_join(pro_th[i], NULL);}lpthread_join(con_th, NULL);lsem_destroy(&(arg.lock));lsem_destroy(&(arg.nempty));lsem_destroy(&(arg.nstored)); } ? build git:(master) ? ./main produce 83 at 0 produce 0 at 1 produce 0 at 2 produce 0 at 3 consume 83 at 0 consume 86 at 1 produce 48 at 4 produce 127 at 0 produce 64 at 1 consume 77 at 2 consume 15 at 3 produce 0 at 2 consume 93 at 4 consume 35 at 0 produce -4 at 3 produce 31 at 4 consume 86 at 1 consume 92 at 2 consume 49 at 3 consume 21 at 42.3.2 多生產(chǎn)者多消費(fèi)者
??多個(gè)生產(chǎn)者和消費(fèi)者互相產(chǎn)生和讀取數(shù)據(jù)。
typedef struct multp_multc_share {int pi;int ci;sem_t nempty;sem_t nstored;sem_t lock;int items;char buff[BUFF_SIZE]; }multp_multc_share;void* multp_multc_produce(void *arg) {multp_multc_share *ptr = arg;for(;;){lsem_wait(&(ptr->nempty));lsem_wait(&(ptr->lock));if(ptr->pi >= ptr->items){lsem_post(&(ptr->nstored));lsem_post(&(ptr->nempty));lsem_post(&(ptr->lock));return NULL;}ptr->buff[ptr->pi % BUFF_SIZE] = rand() % 100;printf("produce %d at %d\n", ptr->buff[ptr->pi * BUFF_SIZE], ptr->pi % BUFF_SIZE);ptr->pi++;lsem_post(&ptr->lock);lsem_post(&ptr->nstored);} }void* multp_multc_consume(void *arg) {multp_multc_share *ptr = arg;for(;;){lsem_wait(&(ptr->nstored));lsem_wait(&(ptr->lock));if(ptr->ci >= ptr->items){lsem_post(&(ptr->nstored));lsem_post(&(ptr->lock));return NULL;}printf("consume %d at %d\n", ptr->buff[ptr->ci % BUFF_SIZE], ptr->ci % BUFF_SIZE);ptr->ci++;lsem_post(&(ptr->lock));lsem_post(&(ptr->nempty));} }void multp_multc_test() {multp_multc_share arg;pthread_t pro_th[THREAD_SIZE], con_th[THREAD_SIZE];arg.items = 10;arg.pi = 0;arg.ci = 0;memset(arg.buff, 0, BUFF_SIZE * sizeof(int));lsem_init(&(arg.lock), 0, 1);lsem_init(&(arg.nempty), 0, BUFF_SIZE);lsem_init(&(arg.nstored), 0, 0);pthread_setconcurrency(THREAD_SIZE + 1); for(int i = 0;i < THREAD_SIZE;i ++){lpthread_create(&pro_th[i], NULL, multp_multc_produce, &arg);}for(int i = 0;i < THREAD_SIZE;i ++){lpthread_create(&con_th[i], NULL, multp_multc_consume, &arg);}for(int i = 0;i < THREAD_SIZE;i ++){lpthread_join(pro_th[i], NULL);}for(int i = 0;i < THREAD_SIZE;i ++){lpthread_join(con_th[i], NULL);}lsem_destroy(&(arg.lock));lsem_destroy(&(arg.nempty));lsem_destroy(&(arg.nstored)); } ? build git:(master) ? ./main produce 83 at 0 produce 0 at 1 produce 0 at 2 produce 0 at 3 consume 83 at 0 consume 86 at 1 consume 77 at 2 produce 1 at 4 produce 0 at 0 produce 0 at 1 produce 0 at 2 consume 15 at 3 consume 93 at 4 consume 35 at 0 consume 86 at 1 produce -2 at 3 consume 92 at 2 produce 98 at 4 consume 49 at 3 consume 21 at 42.3.3 多緩沖讀取
??通過(guò)多緩沖將數(shù)據(jù)從一個(gè)文件寫(xiě)入到另一個(gè)文件。
typedef struct {struct {char buff[MAX_LEN + 1];int len;}buff[BUFF_SIZE];sem_t lock;sem_t nempty;sem_t nstored;int items;int readfd;int writefd; }wr_share;//將buffer中的數(shù)據(jù)寫(xiě)入文件 void *write_buff(void *arg) {wr_share* ptr = arg;int i = 0;while(1){lsem_wait(&ptr->lock);//獲取當(dāng)前緩沖區(qū)的操作lsem_post(&ptr->lock);lsem_wait(&ptr->nstored);lwrite(ptr->writefd, ptr->buff[i].buff, ptr->buff[i].len);lwrite(STDOUT_FILENO, ptr->buff[i].buff, ptr->buff[i].len);i++;if(i >= ptr->items){i = 0;}lsem_post(&ptr->nempty);} }//從文件中讀取數(shù)據(jù) void *read_buff(void *arg) {wr_share* ptr = arg;int i = 0;while(1){lsem_wait(&ptr->lock);//獲取當(dāng)前緩沖區(qū)的操作lsem_post(&ptr->lock);lsem_wait(&ptr->nempty);int n = lread(ptr->readfd, ptr->buff[i].buff, MAX_LEN);ptr->buff[i].len = n;i++;if(i >= ptr->items){i = 0;}lsem_post(&ptr->nstored);} }void read_write_test() {wr_share arg;arg.items = BUFF_SIZE;#if 0char *readfile = "build/CMakeCache.txt";char *writefile = "build/mktmp";#elsechar *readfile = "CMakeCache.txt";char *writefile = "mktmp";#endifarg.readfd = lopen(readfile, O_RDONLY);arg.writefd = lopen(writefile, O_WRONLY | O_CREAT);lsem_init(&arg.lock, 0, 1);lsem_init(&arg.nempty, 0, arg.items);lsem_init(&arg.nstored, 0, 0);pthread_t read_th, write_th;lpthread_create(&read_th, 0, read_buff, &arg);lpthread_create(&write_th, 0, write_buff, &arg);lpthread_join(read_th, NULL);lpthread_join(write_th, NULL);lsem_destroy(&arg.lock);lsem_destroy(&arg.nempty);lsem_destroy(&arg.nstored); }3 System V信號(hào)量
3.1 System V信號(hào)量
??上面提到的Posix信號(hào)量有二值信號(hào)量和計(jì)數(shù)信號(hào)量,而System V信號(hào)量是信號(hào)量集,即一個(gè)或者多個(gè)信號(hào)量構(gòu)成的集合,這個(gè)集合中的信號(hào)量都是計(jì)數(shù)信號(hào)量。
??對(duì)于信號(hào)量集,內(nèi)核維護(hù)的信息結(jié)構(gòu)如下:
??上面的第一個(gè)結(jié)構(gòu)是書(shū)上提到的,下面的第二個(gè)結(jié)構(gòu)是我主機(jī)上的結(jié)構(gòu),我猜測(cè)原理都差不多只是實(shí)現(xiàn)進(jìn)行了修改,因此以書(shū)本上的描述為主。
- sem_perm:用戶(hù)的操作權(quán)限;
- sem_nsems:當(dāng)前數(shù)據(jù)結(jié)構(gòu)中信號(hào)量的數(shù)量;
- sem_otime:上一次調(diào)用apisem_op的時(shí)間;
- sem_ctime:信號(hào)量創(chuàng)建的時(shí)間或上次調(diào)用IPC_SET的時(shí)間。
- semget:創(chuàng)建一個(gè)或者訪(fǎng)問(wèn)一個(gè)已經(jīng)存在的信號(hào)量集;
- key:鍵值;
- nsems:希望初始化的信號(hào)量數(shù)目,初始化之后不可修改,如果只是訪(fǎng)問(wèn)已經(jīng)存在的信號(hào)量集則設(shè)為0;
- semflg:可以為SEM_R,SEM_A分別表示讀和修改,也可以為IPC_CREAT, IPC_EXCL;
- 返回值為信號(hào)量的標(biāo)識(shí)符的整數(shù);
- 當(dāng)創(chuàng)建新的信號(hào)量時(shí),用戶(hù)權(quán)限,讀寫(xiě)權(quán)限,創(chuàng)建時(shí)間,信號(hào)量的數(shù)目都會(huì)設(shè)置,但是結(jié)構(gòu)中的數(shù)組,即各個(gè)信號(hào)量并不會(huì)初始化。這本身是不安全的,即便創(chuàng)建之后立即初始化,因?yàn)椴僮魇欠窃有缘?#xff0c;無(wú)法保證絕對(duì)的安全;
- semop:操作信號(hào)量集,內(nèi)核能夠保證當(dāng)前操作的原子性;
- semid:通過(guò)sem_get獲得的信號(hào)量標(biāo)識(shí)符;
- sops:是一個(gè)如下結(jié)構(gòu)數(shù)據(jù)的數(shù)組,因?yàn)橛行┫到y(tǒng)不會(huì)定義該結(jié)構(gòu),因此有些時(shí)候需要用戶(hù)自己定義:struct sembuf
{
unsigned short int sem_num; /* semaphore number */
short int sem_op; /* semaphore operation */
short int sem_flg; /* operation flag */
};
- sem_num:需要操作的信號(hào)量在信號(hào)量集中的下標(biāo);
- sem_flg:進(jìn)行操作的設(shè)置:
- 0;
- IPC_NOWAIT:不阻塞;
- SEM_UNDO;
- sem_op:具體的操作方式
- sem_op > 0:
- 未設(shè)置SEM_UNDO:將當(dāng)前值加到sem_val上,即sem_val += sem_op,等同于V操作,只不過(guò)釋放線(xiàn)程量可能大于1;
- 設(shè)置SEM_UNDO:從相應(yīng)的信號(hào)量的進(jìn)程調(diào)整值(由內(nèi)核維護(hù))中減去sem_op;
- sem_op == 0:調(diào)用者希望sem_val==0:
- 如果sem_val == 0:立即返回;
- 如果sem_val != 0:對(duì)應(yīng)信號(hào)量的semzcnt += 1,阻塞至為0為止,除非設(shè)置了IPC_NOWAIT,則不阻塞直接返回錯(cuò)誤;
- sem_op < 0:調(diào)用者希望等待sem_val >= |sem_op|用于等待資源:
- 如果sem_val >= |sem_op|,則sem_val -= |sem_op|,若設(shè)置了SEM_UNDO,則將|sem_op|加到對(duì)應(yīng)信號(hào)量的進(jìn)程調(diào)整值上;
- 如果sem_val < |sem_op|,則相應(yīng)信號(hào)量的semncnt += 1,線(xiàn)程被阻塞到滿(mǎn)足條件為止。等到解阻塞時(shí)semval-=|sem_op,并且semncnt -= 1,如果制定了SEM_UNDO則sem_op的絕對(duì)值加到對(duì)應(yīng)信號(hào)量的調(diào)整值上。如果指定了IPC_NOWAIT則線(xiàn)程不會(huì)阻塞。
- 如果一個(gè)被捕獲的信號(hào)喚醒了sem_op或者信號(hào)量被刪除,則該函數(shù)會(huì)過(guò)早的返回一個(gè)錯(cuò)誤。
- sem_op > 0:
- semctl:控制信號(hào)量集;
- semid:信號(hào)量集的標(biāo)識(shí)符;
- semnum:要操作的信號(hào)量的標(biāo)號(hào);
- cmd:命令;
- GETVAL:semval作為返回值返回,-1表示失敗;
- SETVAL:semval設(shè)置為arg.val,成功的話(huà)相應(yīng)信號(hào)量在進(jìn)程中的信號(hào)量調(diào)整值會(huì)設(shè)置為0;
- GETPID:返回sempid;
- GETNCNT:返回semncnt;
- GETZCNT:返回semzcnt;
- GETALL:返回所有信號(hào)量的semval,存入arg.array;
- SETALL:按照arg.array設(shè)置所有信號(hào)量的semval;
- IPC_RMID:刪除指定信號(hào)量集;
- IPC_SET:根據(jù)arg.buf設(shè)置信號(hào)量集的sem_perm.uid,sem_perm.gid,sem_perm.mode;
- IPC_STAT:返回當(dāng)前信號(hào)量集的semid_ds結(jié)構(gòu),存入arg.buf,空間需要用戶(hù)分配。
- arg:可選,根據(jù)cmd指定。
??存在的一些限制:
- semmni:系統(tǒng)范圍內(nèi)最大信號(hào)量集數(shù);
- semmsl:每個(gè)信號(hào)量集最大信號(hào)量數(shù);
- semmns:系統(tǒng)范圍內(nèi)最大信號(hào)量數(shù);
- semopm:每個(gè)semop調(diào)用最大操作數(shù);
- semmnu:系統(tǒng)范圍內(nèi)最大復(fù)舊結(jié)構(gòu)數(shù);
- semume:每個(gè)復(fù)舊結(jié)構(gòu)最大復(fù)舊項(xiàng)數(shù);
- semvmx:任何信號(hào)量的最大值;
- semaem:最大退出時(shí)調(diào)整值。
3.2 示例
int vsem_create(key_t key) {int semid = lsemget(key, 1, 0666 | IPC_CREAT | IPC_EXCL);return semid; }int vsem_open(key_t key) {int semid = lsemget(key, 0, 0);//創(chuàng)建一個(gè)信號(hào)量集 return semid; }int vsem_p(int semid)// {struct sembuf sb = {0, -1, /*IPC_NOWAIT*/SEM_UNDO};//對(duì)信號(hào)量集中第一個(gè)信號(hào)進(jìn)行操作,對(duì)信號(hào)量的計(jì)數(shù)值減1,lsemop(semid, &sb, 1);//用來(lái)進(jìn)行P操作 return 0; }int vsem_v(int semid) {struct sembuf sb = {0, 1, /*0*/SEM_UNDO};lsemop(semid, &sb, 1);return 0; }int vsem_d(int semid) {int ret = semctl(semid, 0, IPC_RMID, 0);//刪除一個(gè)信號(hào)量集return ret; }int vsem_setval(int semid, int val) {union semun su;su.val = val;semctl(semid, 0, SETVAL, &su);//給信號(hào)量計(jì)數(shù)值printf("value updated...\n");return 0; }int vsem_getval(int semid)//獲取信號(hào)量集中信號(hào)量的計(jì)數(shù)值 {int ret = semctl(semid, 0, GETVAL, 0);//返回值是信號(hào)量集中printf("current val is %d\n", ret);return ret; }int vsem_getmode(int semid) {union semun su;struct semid_ds sem;su.buf = &sem;semctl(semid, 0, IPC_STAT, su);printf("current permissions is %o\n", su.buf->sem_perm.mode);return 0; }int vsem_setmode(int semid, char *mode) {union semun su;struct semid_ds sem;su.buf = &sem;semctl(semid, 0, IPC_STAT, su);printf("current permissions is %o\n", su.buf->sem_perm.mode);sscanf(mode, "%o", (unsigned int *)&su.buf->sem_perm.mode);semctl(semid, 0, IPC_SET, &su);printf("permissions updated...\n");return 0; }void usage(void) {fprintf(stderr, "usage:\n");fprintf(stderr, "semtool -c\n");fprintf(stderr, "semtool -d\n");fprintf(stderr, "semtool -p\n");fprintf(stderr, "semtool -v\n");fprintf(stderr, "semtool -s <val>\n");fprintf(stderr, "semtool -g\n");fprintf(stderr, "semtool -f\n");fprintf(stderr, "semtool -m <mode>\n"); }void v_test(int argc, char *argv[]) {int opt;opt = getopt(argc, argv, "cdpvs:gfm:");//解析參數(shù)if (opt == '?')exit(EXIT_FAILURE);if (opt == -1){usage();exit(EXIT_FAILURE);}key_t key = ftok(".", 's');int semid;switch (opt){case 'c'://創(chuàng)建信號(hào)量集vsem_create(key);break;case 'p'://p操作semid = vsem_open(key);vsem_p(semid);vsem_getval(semid);break;case 'v'://v操作semid = vsem_open(key);vsem_v(semid);vsem_getval(semid);break;case 'd'://刪除一個(gè)信號(hào)量集semid = vsem_open(key);vsem_d(semid);break;case 's'://對(duì)信號(hào)量集中信號(hào)量設(shè)置初始計(jì)數(shù)值semid = vsem_open(key);vsem_setval(semid, atoi(optarg));break;case 'g'://獲取信號(hào)量集中信號(hào)量的計(jì)數(shù)值semid = vsem_open(key);vsem_getval(semid);break;case 'f'://查看信號(hào)量集中信號(hào)量的權(quán)限semid = vsem_open(key);vsem_getmode(semid);break;case 'm'://更改權(quán)限semid = vsem_open(key);vsem_setmode(semid, argv[2]);break;}return; }總結(jié)
以上是生活随笔為你收集整理的Linux进程通信之信号量的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java 关机命令_(windows )
- 下一篇: mysql8忘记密码后重置密码