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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > linux >内容正文

linux

判断sem信号量为零_Linux系统编程——进程同步与互斥:System V 信号量

發(fā)布時(shí)間:2025/4/5 linux 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 判断sem信号量为零_Linux系统编程——进程同步与互斥:System V 信号量 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

信號(hào)量概述

信號(hào)量廣泛用于進(jìn)程或線程間的同步和互斥,信號(hào)量本質(zhì)上是一個(gè)非負(fù)的整數(shù)計(jì)數(shù)器,它被用來(lái)控制對(duì)公共資源的訪問(wèn)。

編程時(shí)可根據(jù)操作信號(hào)量值的結(jié)果判斷是否對(duì)公共資源具有訪問(wèn)的權(quán)限,當(dāng)信號(hào)量值大于 0 時(shí),則可以訪問(wèn),否則將阻塞。PV 原語(yǔ)是對(duì)信號(hào)量的操作,一次 P 操作使信號(hào)量減1,一次 V 操作使信號(hào)量加1。

在實(shí)際應(yīng)用中兩個(gè)進(jìn)程間通信可能會(huì)使用多個(gè)信號(hào)量,因此 System V 的信號(hào)量以集合的概念來(lái)管理,具體操作和 Posix 信號(hào)量大同小異。

信號(hào)量集合數(shù)據(jù)結(jié)構(gòu):struct semid_ds,此數(shù)據(jù)結(jié)構(gòu)中定義了整個(gè)信號(hào)量集的基本屬性。

/* Obsolete, used only for backwards compatibility and libc5 compiles */struct semid_ds{struct ipc_permsem_perm;/* permissions .. see ipc.h */__kernel_time_tsem_otime;/* last semop time */__kernel_time_tsem_ctime;/* last change time */struct sem*sem_base;/* ptr to first semaphore in array */struct sem_queue *sem_pending;/* pending operations to be processed */struct sem_queue **sem_pending_last;/* last pending operation */struct sem_undo*undo;/* undo requests on this array */unsigned shortsem_nsems;/* no. of semaphores in array */};

信號(hào)量數(shù)據(jù)結(jié)構(gòu):struct sem,此數(shù)據(jù)結(jié)構(gòu)中定義了信號(hào)量的基本屬性。

/* One semaphore structure for each semaphore in the system. */struct sem{intsemval;/* current value *信號(hào)量的值*/intsempid;/* pid of last operation *最后一個(gè)操作信號(hào)量的進(jìn)程號(hào)*/struct list_head sem_pending; /* pending single-sop operations */};

System V 信號(hào)量基本操作

使用 shell 命令操作信號(hào)量:

查看信號(hào)量:ipcs -s刪除信號(hào)量:ipcrm -s?semid

以下函數(shù)所需頭文件如下:

#include #include #include

1)創(chuàng)建信號(hào)量集合

int semget(key_t key, int nsems, int semflg);

功能:

創(chuàng)建或打開(kāi)一個(gè)信號(hào)量集合,該集合中可以包含多個(gè)信號(hào)量。

參數(shù):

key:進(jìn)程間通信鍵值,通過(guò)調(diào)用 ftok() 函數(shù)得到的鍵值

nsems:創(chuàng)建的信號(hào)量的個(gè)數(shù)。如果只是訪問(wèn)而不創(chuàng)建則可以指定該參數(shù)為 0,一旦創(chuàng)建了該信號(hào)量,就不能更改其信號(hào)量個(gè)數(shù),只要不刪除該信號(hào)量,重新調(diào)用該函數(shù)創(chuàng)建該鍵值的信號(hào)量,該函數(shù)只是返回以前創(chuàng)建的值,不會(huì)重新創(chuàng)建。

semflg:標(biāo)識(shí)函數(shù)的行為及信號(hào)量的權(quán)限,其取值如下:

  • IPC_CREAT:創(chuàng)建信號(hào)量。
  • IPC_EXCL:檢測(cè)信號(hào)量是否存在。
  • 位或權(quán)限位:信號(hào)量位或權(quán)限位后可以設(shè)置信號(hào)量的訪問(wèn)權(quán)限,格式和 open 函數(shù)的 mode_ t 一樣(open() 的使用請(qǐng)點(diǎn)此鏈接),但可執(zhí)行權(quán)限未使用。

返回值:

成功:信號(hào)量集標(biāo)識(shí)符

失敗:返回 -1

2)控制信號(hào)量集合、信號(hào)量

int semctl(int semid, int semnum, int cmd, ...);

功能:

對(duì)信號(hào)量集合以及集合中的信號(hào)量進(jìn)行操作。

參數(shù):

semid:信號(hào)量集標(biāo)識(shí)符。

semnum:集合中信號(hào)量的序號(hào),指定對(duì)哪個(gè)信號(hào)量操作, 只對(duì)幾個(gè)特殊的 cmd 操作有意義。

cmd:信號(hào)量控制類(lèi)型。semctl() 函數(shù)可能有3個(gè)參數(shù),也可能有4個(gè)參數(shù),參數(shù)的個(gè)數(shù)由 cmd 決定。當(dāng)有4個(gè)參數(shù)時(shí),第4個(gè)參數(shù)為聯(lián)合體:

union semun{intval;/*信號(hào)量的值*/struct semid_ds *buf;/*信號(hào)量集合信息*/unsigned short *array;/*信號(hào)量值的數(shù)組*/struct seminfo *__buf;/*信號(hào)量限制信息*/};

cmd 的取值如下:

GETVAL:獲取信號(hào)量的值。此時(shí)函數(shù)有3個(gè)參數(shù)。semctl() 函數(shù)的返回值即為信號(hào)量的值。

SETVAL:設(shè)置信號(hào)量的值。此時(shí)函數(shù)有4個(gè)參數(shù)。第4個(gè)參數(shù)為聯(lián)合體中的val,其值為信號(hào)量的值。

IPC_STAT:獲取信號(hào)量集合的信息。此時(shí)函數(shù)有4個(gè)參數(shù)。第4個(gè)參數(shù)為聯(lián)合體中的__buf。

IPC_SET:設(shè)置信號(hào)量集合的信息。此時(shí)函數(shù)有4個(gè)參數(shù)。第4個(gè)參數(shù)為聯(lián)合體中的__buf。

IPC_RMID:刪除信號(hào)量集。此時(shí)函數(shù)有3個(gè)參數(shù),第2個(gè)參數(shù)semnum不起作用。

GETALL:獲取所有信號(hào)量的值。此時(shí)函數(shù)有4個(gè)參數(shù),第2個(gè)參數(shù)semnum不起作用。第4個(gè)參數(shù)為聯(lián)合體中的array,其值為用來(lái)存放所有信號(hào)量值的數(shù)組的首地址。

SETALL:設(shè)置所有信號(hào)量的值 。參數(shù)說(shuō)明同上。

IPC_INFO:獲取信號(hào)量集合的限制信息。此時(shí)函數(shù)有4個(gè)參數(shù),第2個(gè)參數(shù)semnum不起作用。第4個(gè)參數(shù)為聯(lián)合體中的__buf。

GETPID:獲取信號(hào)的進(jìn)程號(hào),即最后操作信號(hào)量的進(jìn)程。此時(shí)函數(shù)有3個(gè)參數(shù)。semctl() 函數(shù)的返回值即為信號(hào)的進(jìn)程號(hào)。

GETNCNT:獲取等待信號(hào)的值遞增的進(jìn)程數(shù)。此時(shí)函數(shù)有3個(gè)參數(shù)。semctl() 函數(shù)的返回值即為進(jìn)程數(shù)。

GETZCNT:獲取等待信號(hào)的值遞減的進(jìn)程數(shù)。此時(shí)函數(shù)有3個(gè)參數(shù)。semctl() 函數(shù)的返回值即為進(jìn)程數(shù)。

返回值:

成功:0

失敗:-1

3)操作信號(hào)量

int semop(int semid, struct sembuf *sops, unsigned nsops);

功能:

操作信號(hào)量,主要進(jìn)行信號(hào)量加減操作。

參數(shù):

semid:信號(hào)量集標(biāo)識(shí)符。

sops:操作信號(hào)量的結(jié)構(gòu)體(struct sembuf)數(shù)組的首地址( 結(jié)構(gòu)體定義在 sys/sem.h ),此結(jié)構(gòu)體中的數(shù)據(jù)表明了對(duì)信號(hào)量進(jìn)行的操作。

struct sembuf{unsigned short sem_num;/*信號(hào)量的序號(hào)*/short sem_op;/*信號(hào)量的操作值*/short sem_flg;/*信號(hào)量的操作標(biāo)識(shí)*/};

結(jié)構(gòu)體成員使用說(shuō)明如下:

sem_num:信號(hào)量集中信號(hào)量的序號(hào)

sem_op 取值如下:

sem_op > 0:信號(hào)量的值在原來(lái)的基礎(chǔ)上加上此值。

sem_op < 0:如果信號(hào)量的值小于 semop 的絕對(duì)值,則掛起操作進(jìn)程。如果信號(hào)量的值大于等于 semop 的絕對(duì)值,則信號(hào)量的值在原來(lái)的基礎(chǔ)上減去 semop 的絕對(duì)值。

sem_op = 0:對(duì)信號(hào)量的值進(jìn)行是否為 0 測(cè)試。若為 0 則函數(shù)立即返回,若不為 0 則阻塞調(diào)用進(jìn)程。

sem_flag 取值如下:

IPC_NOWAIT:在對(duì)信號(hào)量的操作不能執(zhí)行的情況下使函數(shù)立即返回。

SEM_UNDO:當(dāng)進(jìn)程退出后,該進(jìn)程對(duì)信號(hào)量進(jìn)行的操作將被撤銷(xiāo)。

nsops:操作信號(hào)量的結(jié)構(gòu)體數(shù)組中元素的個(gè)數(shù)。

返回值:

成功:0

失敗:-1

使用示例

示例一:

#include #include #include #include #include int main(int argc, char *argv[]){key_t key; //創(chuàng)建key值key = ftok(".", 'a');if(key == -1){perror("ftok");}//查看信號(hào)量system("ipcs -s");int semid;//1: 創(chuàng)建的信號(hào)量的個(gè)數(shù)semid = semget(key, 1, IPC_CREAT|0666); //創(chuàng)建信號(hào)量if(semid == -1){perror("semget");}system("ipcs -s"); //查看信號(hào)量//刪去信號(hào)量// 0: 代表對(duì)第0個(gè)信號(hào)量進(jìn)行操作// IPC_RMID:刪除信號(hào)量集semctl(semid, 0, IPC_RMID);system("ipcs -s"); //查看信號(hào)量return 0;}

運(yùn)行結(jié)果如下:

示例二:

#include #include #include #include #include /*解決編譯出錯(cuò)的問(wèn)題*/#define IPC_INFO 3 int main(int argc, char *argv[]){key_t key; //創(chuàng)建key值key = ftok(".", 'a');if(key == -1){perror("ftok");}system("ipcs -s"); //查看信號(hào)量int semid;//1: 創(chuàng)建的信號(hào)量的個(gè)數(shù)semid = semget(key, 1, IPC_CREAT|0666);//創(chuàng)建信號(hào)量if(semid == -1){perror("semget");}system("ipcs -s"); //查看信號(hào)量struct seminfo buf;/*//struct seminfo相關(guān)成員struct seminfo {int semmap;int semmni;int semmns;int semmnu;int semmsl;int semopm;int semume;int semusz;int semvmx;int semaem;};*///IPC_INFO:獲取信號(hào)量集合的限制信息。//此時(shí)函數(shù)有4個(gè)參數(shù),第2個(gè)參數(shù)semnum不起作用。semctl(semid, 0, IPC_INFO, &buf);printf("buf.semmni = %d", buf.semmni);printf("buf.semmns = %d", buf.semmns);printf("buf.semmnu = %d", buf.semmnu);printf("buf.semmsl = %d", buf.semmsl);printf("buf.semopm = %d", buf.semopm);printf("buf.semume = %d", buf.semume);printf("buf.semusz = %d", buf.semusz);printf("buf.semvmx = %d", buf.semvmx);printf("buf.semaem = %d", buf.semaem); //刪去信號(hào)量// 0: 代表對(duì)第0個(gè)信號(hào)量進(jìn)行操作// IPC_RMID:刪除信號(hào)量集semctl(semid, 0, IPC_RMID);system("ipcs -s"); //查看信號(hào)量return 0;}

運(yùn)行結(jié)果如下:

示例三:

#include #include #include #include #include int main(int argc, char *argv[]){key_t key; //創(chuàng)建key值key = ftok(".", 'a');if(key == -1){perror("ftok");}//查看信號(hào)量system("ipcs -s");int semid;//1: 創(chuàng)建的信號(hào)量的個(gè)數(shù)semid = semget(key, 1, IPC_CREAT|0666); //創(chuàng)建信號(hào)量if(semid == -1){perror("semget");}system("ipcs -s"); //查看信號(hào)量int ret;/*//SETVAL: 設(shè)置信號(hào)量的值。此時(shí)函數(shù)有4個(gè)參數(shù)。第4個(gè)參數(shù)為聯(lián)合體中的val,其值為信號(hào)量的值。 union semun{intval;//信號(hào)量的值struct semid_ds *buf;//信號(hào)量集合信息unsigned short *array;//信號(hào)量值的數(shù)組struct seminfo *__buf;//信號(hào)量限制信息};*/ret = semctl(semid, 0, SETVAL, 20);if(ret == -1){perror("semctl");}//GETVAL:獲取信號(hào)量的值。函數(shù)返回值即為信號(hào)量的值。ret = semctl(semid, 0, GETVAL);if(ret == -1){perror("semctl");}printf("ret = %d", ret); // 0: 代表對(duì)第0個(gè)信號(hào)量進(jìn)行操作// IPC_RMID:刪除信號(hào)量集semctl(semid, 0, IPC_RMID);system("ipcs -s");return 0;}

運(yùn)行結(jié)果如下:

示例四:

#include #include #include #include #include #include int main(int argc, char *argv[]){key_t key; //創(chuàng)建key值key = ftok(".", 'a');if(key == -1){perror("ftok");}//查看信號(hào)量system("ipcs -s");int semid;//2: 創(chuàng)建的信號(hào)量的個(gè)數(shù)semid = semget(key, 2, IPC_CREAT|0666); //創(chuàng)建信號(hào)量if(semid == -1){perror("semget");}system("ipcs -s"); //查看信號(hào)量int ret; unsigned short sem_arry[2] = {30,20};/*//SETALL: 設(shè)置所有信號(hào)量的值。此時(shí)函數(shù)有4個(gè)參數(shù),第2個(gè)參數(shù)semnum不起作用。第4個(gè)參數(shù)為聯(lián)合體中的array,其值為用來(lái)存放所有信號(hào)量值的數(shù)組的首地址。union semun{intval;//信號(hào)量的值struct semid_ds *buf;//信號(hào)量集合信息unsigned short *array;//信號(hào)量值的數(shù)組struct seminfo *__buf;//信號(hào)量限制信息};*/ret = semctl(semid, 0, SETALL, sem_arry);if(ret == -1){perror("semctl");}bzero(sem_arry, sizeof(sem_arry));//GETALL:獲取所有信號(hào)量的值。此時(shí)函數(shù)有4個(gè)參數(shù),第2個(gè)參數(shù)semnum不起作用。第4個(gè)參數(shù)為聯(lián)合體中的array,其值為用來(lái)存放所有信號(hào)量值的數(shù)組的首地址。ret = semctl(semid, 0, GETALL, sem_arry);if(ret == -1){perror("semctl");}printf("sem_arry[0] = %d", sem_arry[0]);printf("sem_arry[1] = %d", sem_arry[1]); // IPC_RMID:刪除信號(hào)量集semctl(semid, 0, IPC_RMID);system("ipcs -s");return 0;}

運(yùn)行結(jié)果如下:

示例五:

//此范例使用信號(hào)量來(lái)同步共享內(nèi)存的操作#include #include #include #include #include #include #include #define SHM_KEY 0x33 #define SEM_KEY 0x44 union semun { int val; struct semid_ds *buf; unsigned short *array; }; int P(int semid) { struct sembuf sb;/*//操作信號(hào)量的結(jié)構(gòu)體struct sembuf{unsigned short sem_num;//信號(hào)量的序號(hào)short sem_op;//信號(hào)量的操作值short sem_flg;//信號(hào)量的操作標(biāo)識(shí)};*/sb.sem_num = 0; sb.sem_op = -1;//SEM_UNDO:當(dāng)進(jìn)程退出后,該進(jìn)程對(duì)信號(hào)量進(jìn)行的操作將被撤銷(xiāo)。sb.sem_flg = SEM_UNDO; //操作1個(gè)信號(hào)量if(semop(semid, &sb, 1) == -1){ perror("semop"); return -1; } return 0; } int V(int semid) { struct sembuf sb;/*//操作信號(hào)量的結(jié)構(gòu)體struct sembuf{unsigned short sem_num;//信號(hào)量的序號(hào)short sem_op;//信號(hào)量的操作值short sem_flg;//信號(hào)量的操作標(biāo)識(shí)};*/sb.sem_num = 0; sb.sem_op = 1;//SEM_UNDO:當(dāng)進(jìn)程退出后,該進(jìn)程對(duì)信號(hào)量進(jìn)行的操作將被撤銷(xiāo)。sb.sem_flg = SEM_UNDO; //操作1個(gè)信號(hào)量if(semop(semid, &sb, 1) == -1){ perror("semop"); return -1; } return 0; } int main(int argc, char **argv) {pid_t pid; int i, shmid, semid; int *ptr = NULL; union semun semopts; /*union semun{intval;//信號(hào)量的值struct semid_ds *buf;//信號(hào)量集合信息unsigned short *array;//信號(hào)量值的數(shù)組struct seminfo *__buf;//信號(hào)量限制信息};*/ //創(chuàng)建一塊共享內(nèi)存, 存一個(gè)int變量if ((shmid = shmget(SHM_KEY, sizeof(int), IPC_CREAT | 0600)) == -1) { perror("msgget"); return -1;} //將共享內(nèi)存映射到進(jìn)程, fork后子進(jìn)程可以繼承映射ptr = (int *)shmat(shmid, NULL, 0);if (ptr == (int *)-1) { perror("shmat");return -1;}*ptr = 0; //賦值為0 // 創(chuàng)建一個(gè)信號(hào)量用來(lái)同步共享內(nèi)存的操作 if ((semid = semget(SEM_KEY, 1, IPC_CREAT | 0600)) == -1) { perror("semget"); return -1;} //初始化信號(hào)量 semopts.val = 1; if (semctl(semid, 0, SETVAL, semopts) < 0) { perror("semctl"); return -1;} if ((pid = fork()) < 0) { //創(chuàng)建進(jìn)程perror("fork");_exit(0);}else if (pid == 0){ // Child// 子進(jìn)程對(duì)共享內(nèi)存加1 for (i = 0; i < 100000; i++) { P(semid); (*ptr)++; V(semid); printf("child: %d", *ptr); } } else { //Parent// 父進(jìn)程對(duì)共享內(nèi)存減1 for (i = 0; i < 100000; i++) { P(semid); (*ptr)--; V(semid); printf("parent: %d", *ptr); } //如果子進(jìn)程結(jié)束,回收其資源wait(NULL);//如果同步成功, 共享內(nèi)存的值為0 printf("finally: %d", *ptr); } return 0; }

運(yùn)行結(jié)果如下:

需要C/C++ Linux服務(wù)器架構(gòu)師學(xué)習(xí)資料私信“資料”(資料包括C/C++,Linux,golang技術(shù),Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,TCP/IP,協(xié)程,DPDK,ffmpeg等),免費(fèi)分享

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的判断sem信号量为零_Linux系统编程——进程同步与互斥:System V 信号量的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。