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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

封装一个信号量集操作函数的工具

發(fā)布時間:2025/3/17 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 封装一个信号量集操作函数的工具 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

信號量的概念參見這里。

與消息隊列和共享內存一樣,信號量集也有自己的數(shù)據(jù)結構:

struct semid_ds {
struct ipc_perm sem_perm; ?/* Ownership and permissions */
time_t ? ? sem_otime; /* Last semop time */
time_t ? ? sem_ctime; /* Last change time */
unsigned short ?sem_nsems; /* No. of semaphores in set */
};


同樣地,第一個條目也是共有的ipc 對象內核結構,剩下的是私有成員。


?Each semaphore in a semaphore set has the following associated values:

? ? ? ? ? ?unsigned short ?semval; ? /* semaphore value */
? ? ? ? ? ?unsigned short ?semzcnt; ?/* # waiting for zero */
? ? ? ? ? ?unsigned short ?semncnt; ?/* # waiting for increase */
? ? ? ? ? ?pid_t ? ? ? ? ? sempid; ? /* process that did last op */

即每一個在信號量集中的信號量都有上述4個相關的變量。

1、semval :當前某信號量的資源數(shù)目

2、semzcnt:當sem_op(見 struct sembuf)為0,且semop 函數(shù)沒有設置IPC_NOWAIT 標志,且當前semval 不為0,此時semzcnt 會加1,表示等待這個信號量的資源變?yōu)?的進程數(shù)加1,且進程會阻塞等待直到4個事件其中一個發(fā)生,具體可man 2 semop 一下。

3、semncnt:當sem_op(見 struct sembuf)< 0,且semop 函數(shù)沒有設置IPC_NOWAIT 標志,且當前semval < |sem_op| ,此時semncnt 會加1,表示等待這個信號量的資源增加的進程數(shù)加1,且進程會阻塞等待直到4個事件其中一個發(fā)生,具體可man 2 semop 一下。

4、當正確執(zhí)行了semop 函數(shù),則信號量集中的每個信號量的sempid 參數(shù)都被設置為改變此信號量的進程pid。


以下是幾個信號量集操作函數(shù):

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int semget(key_t key, int nsems, int semflg);
int semctl(int semid, int semnum, int cmd, ...);
int semop(int semid, struct sembuf *sops, unsigned nsops);


功能:用來創(chuàng)建和訪問一個信號量集
原型 int semget(key_t key, int nsems, int semflg);
參數(shù)
key: 信號量集的名字
nsems:信號量集中信號量的個數(shù)
semflg: 由九個權限標志構成,它們的用法和創(chuàng)建文件時使用的mode模式標志是一樣的
返回值:成功返回一個非負整數(shù),即該信號量集的標識碼;失敗返回-1


功能:用于控制信號量集
原型 int semctl(int semid, int semnum, int cmd, ...);
參數(shù)
semid:由semget返回的信號量集標識碼
semnum:信號量集中信號量的序號,從0開始編號
cmd:將要采取的動作(有三個可取值)
最后一個參數(shù)是 union semun,具體成員根據(jù)cmd 的不同而不同

union semun {
? ? ? ? ? ? ? ?int ? ? ? ? ? ? ?val; ? ?/* Value for SETVAL */
? ? ? ? ? ? ? ?struct semid_ds *buf; ? ?/* Buffer for IPC_STAT, IPC_SET */
? ? ? ? ? ? ? ?unsigned short ?*array; ?/* Array for GETALL, SETALL */
? ? ? ? ? ? ? ?struct seminfo ?*__buf; ?/* Buffer for IPC_INFO?(Linux-specific) */
? ? ? ? ? ?};
返回值:成功返回0;失敗返回-1

cmd 取值如下:

SETVAL ?設置信號量集中的信號量的計數(shù)值
GETVAL ?獲取信號量集中的信號量的計數(shù)值
IPC_STAT 把semid_ds結構中的數(shù)據(jù)設置為信號量集的當前關聯(lián)值
IPC_SET 在進程有足夠權限的前提下,把信號量集的當前關聯(lián)值設置為semid_ds數(shù)據(jù)結構中給出的值
IPC_RMID 刪除信號量集


功能:用來創(chuàng)建和訪問一個信號量集
原型 int semop(int semid, struct sembuf *sops, unsigned nsops);
參數(shù)
semid:是該信號量集的標識碼,也就是semget函數(shù)的返回值
sops:是個指向一個結構體的指針
nsops:信號量的個數(shù)
返回值:成功返回0;失敗返回-1

struct sembuf

{?

unsigned short sem_num; ?/* semaphore number */
? ? ? ? ? ?short ? ? ? ? ?sem_op; ? /* semaphore operation */
? ? ? ? ? ?short ? ? ? ? ?sem_flg; ?/* operation flags */

};

sem_num:是信號量的編號。


sem_op:是信號量一次PV操作時加減的數(shù)值,一般只會用到兩個值,一個是“-1”,也就是P操作,等待信號量變得可用;另一個是“+1”,也就是我們的V操作,發(fā)出信號量已經(jīng)變得可用。當然+-n 和0 都是允許的。需要注意的是只有+n 才確保將semval +n 后馬上返回,而-n 和 0 很可能是會阻塞的,見文章上面的分析,+-n 需要進程對信號量集有寫的權限,而0 只需要讀的權限。


sem_flag:的兩個取值是IPC_NOWAIT或SEM_UNDO,設為前者如果當某個信號量的資源為0時進行P操作,此時不會阻塞等待,而是直接返回資源不可用的錯誤;設為后者,當退出進程時對信號量資源的操作撤銷;不關心時設置為0即可。

當要對一個信號量集中的多個信號量進行操作時,sops 是結構體數(shù)組的指針,此時nsops 不為1。此時對多個信號量的操作是作為一個單元原子操作,要么全部執(zhí)行,要么全部不執(zhí)行。


下面來封裝一個信號量集操作函數(shù)的工具:

semtool.c

?

C++ Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
? #include?<sys/types.h>
#include?<unistd.h>
#include?<sys/ipc.h>
#include?<sys/sem.h>
#include?<errno.h>
#include?<stdio.h>
#include?<stdlib.h>

#define?ERR_EXIT(m)?\
????????do?\
????????{?\
????????????????perror(m);?\
????????????????exit(EXIT_FAILURE);?\
????????}?while(0)

union?semun
{
????int?val;??????????????????/*?value?for?SETVAL?*/
????struct?semid_ds?*buf;?????/*?buffer?for?IPC_STAT,?IPC_SET?*/
????unsigned?short?*array;????/*?array?for?GETALL,?SETALL?*/
????/*?Linux?specific?part:?*/
????struct?seminfo?*__buf;????/*?buffer?for?IPC_INFO?*/
};

int?sem_create(key_t?key)
{
????int?semid?=?semget(key,?1,?0666?|?IPC_CREAT?|?IPC_EXCL);
????if?(semid?==?-1)
????????ERR_EXIT("semget");

????return?semid;
}

int?sem_open(key_t?key)
{
????int?semid?=?semget(key,?0,?0);
????if?(semid?==?-1)
????????ERR_EXIT("semget");

????return?semid;
}

int?sem_p(int?semid)
{
????struct?sembuf?sb?=?{0,?-1,?/*IPC_NOWAIT*/SEM_UNDO};
????int?ret?=?semop(semid,?&sb,?1);
????if?(ret?==?-1)
????????ERR_EXIT("semop");

????return?ret;
}

int?sem_v(int?semid)
{
????struct?sembuf?sb?=?{0,?1,?/*0*/SEM_UNDO};
????int?ret?=?semop(semid,?&sb,?1);
????if?(ret?==?-1)
????????ERR_EXIT("semop");

????return?ret;
}

int?sem_d(int?semid)
{
????int?ret?=?semctl(semid,?0,?IPC_RMID,?0);
????if?(ret?==?-1)
????????ERR_EXIT("semctl");
????return?ret;
}

int?sem_setval(int?semid,?int?val)
{
????union?semun?su;
????su.val?=?val;
????int?ret?=?semctl(semid,?0,?SETVAL,?su);
????if?(ret?==?-1)
????????ERR_EXIT("semctl");

????printf("value?updated...\n");
????return?ret;
}

int?sem_getval(int?semid)
{
????int?ret?=?semctl(semid,?0,?GETVAL,?0);
????if?(ret?==?-1)
????????ERR_EXIT("semctl");

????printf("current?val?is?%d\n",?ret);
????return?ret;
}

int?sem_getmode(int?semid)
{
????union?semun?su;
????struct?semid_ds?sem;
????su.buf?=?&sem;
????int?ret?=?semctl(semid,?0,?IPC_STAT,?su);
????if?(ret?==?-1)
????????ERR_EXIT("semctl");

????printf("current?permissions?is?%o\n",?su.buf->sem_perm.mode);
????return?ret;
}

int?sem_setmode(int?semid,?char?*mode)
{
????union?semun?su;
????struct?semid_ds?sem;
????su.buf?=?&sem;

????int?ret?=?semctl(semid,?0,?IPC_STAT,?su);
????if?(ret?==?-1)
????????ERR_EXIT("semctl");

????printf("current?permissions?is?%o\n",?su.buf->sem_perm.mode);
????sscanf(mode,?"%o",?(unsigned?int?*)&su.buf->sem_perm.mode);
????ret?=?semctl(semid,?0,?IPC_SET,?su);
????if?(ret?==?-1)
????????ERR_EXIT("semctl");

????printf("permissions?updated...\n");

????return?ret;
}

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");
}

int?main(int?argc,?char?*argv[])
{
????int?opt;

????opt?=?getopt(argc,?argv,?"cdpvs:gfm:");
????if?(opt?==?'?')
????????exit(EXIT_FAILURE);
????if?(opt?==?-1)
????{
????????usage();
????????exit(EXIT_FAILURE);
????}

????key_t?key?=?ftok(".",?'s');
????int?semid;
????switch?(opt)
????{
????case?'c':
????????sem_create(key);
????????break;
????case?'p':
????????semid?=?sem_open(key);
????????sem_p(semid);
????????sem_getval(semid);
????????break;
????case?'v':
????????semid?=?sem_open(key);
????????sem_v(semid);
????????sem_getval(semid);
????????break;
????case?'d':
????????semid?=?sem_open(key);
????????sem_d(semid);
????????break;
????case?'s':
????????semid?=?sem_open(key);
????????sem_setval(semid,?atoi(optarg));
????????break;
????case?'g':
????????semid?=?sem_open(key);
????????sem_getval(semid);
????????break;
????case?'f':
????????semid?=?sem_open(key);
????????sem_getmode(semid);
????????break;
????case?'m':
????????semid?=?sem_open(key);
????????sem_setmode(semid,?argv[2]);
????????break;
????}

????return?0;
}

首先來介紹一個getopt 函數(shù),?int getopt(int argc, char * const argv[],const char *optstring);

可以解析命令行選項參數(shù),前兩個參數(shù)由main 函數(shù)傳遞,第三個參數(shù)是一個字符串集,即解析命令行參數(shù)看是否存在這些字符。如./semtool -s 3 則s

為選項,3為選項參數(shù),optarg 是一個全局指針變量??extern char *optarg; ?通過atoi(optarg) 可以獲取數(shù)字3。



使用方法。


// optind: the index of first argument which has no option


// after getopt loop end: ./main -a xxx -b xxx ip port cnt ? ?optind points to ip


// usually optind+1 <= argc when no option arguments needed.

// argc: the count of arguments include exe; agrv[0 ~ argc-1]




key 已存在時返回錯誤,不再創(chuàng)建信號量集,而我們使用了ftok 函數(shù)產生一個唯一的key,傳入的參數(shù)一定,則每次產生的key 值


樣,當?shù)诙未螆?zhí)行./semtool -c ,會返回file exist 的錯誤,當然先刪除當前信號量集,再create 是可以的,此時雖然key 還是一樣


的,但返回的semid 是不同的。




simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ ipcs -s


------ Semaphore Arrays --------
key ? ? ? ?semid ? ? ?owner ? ? ?perms ? ? ?nsems ? ??


simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ ./semtool?
usage:

semtool -c

semtool -d

semtool -p

semtool -v

semtool -s <val>

semtool -g

semtool -f

semtool -m <mode>

simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ ./semtool -c

simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ ipcs -s


------ Semaphore Arrays --------
key ? ? ? ? semid ? ? ?owner ? ? ?perms ? ? ?nsems ? ??
0x730135db ?98304 ? ? ?simba ? ? ?666 ? ? ? ? ? 1 ? ? ? ??


simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ ./semtool -v

current val is 1
simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$?

simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ ./semtool -v

current val is 1

simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ ./semtool -s 3

value updated...

simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ ./semtool -g

current val is 3

simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ ./semtool -p

current val is 2

simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ ./semtool -m 600

current permissions is 666

permissions updated...

simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ ./semtool -d

simba@ubuntu:~/Documents/code/linux_programming/UNP/system_v$ ipcs -s


------ Semaphore Arrays --------
key ? ? ? ?semid ? ? ?owner ? ? ?perms ? ? ?nsems ? ??

可以設置信號量的資源數(shù)。ipcs -s 輸出中的nsems 表示信號量的個數(shù),當前只有一個;./semtool -v 輸出中的current value 表示這個信號量的資源數(shù)。


參考:《UNP》

新人創(chuàng)作打卡挑戰(zhàn)賽發(fā)博客就能抽獎!定制產品紅包拿不停!

總結

以上是生活随笔為你收集整理的封装一个信号量集操作函数的工具的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 一区二区三区日韩 | 成人国产精品视频 | 日韩在线观看视频一区二区三区 | 久久国产精品波多野结衣av | 国产精品一区二区电影 | 公侵犯一区二区三区四区中文字幕 | 久久91亚洲 | 91麻豆国产 | 中文字幕mv | 超碰国产人人 | 先锋av资源网 | 无码av免费精品一区二区三区 | 后进极品美女白嫩翘臀 | 日韩va亚洲va欧美va久久 | 玖玖爱在线观看 | 神马午夜av | 国产精品久久久久久久久久久久久久久 | 亚洲网在线观看 | 亚洲国产精品国自产拍久久 | 在线观看的网站 | 9l蝌蚪porny中文自拍 | 欧美做爰猛烈床戏大尺度 | 国产原创麻豆 | 色呦网站 | 欧美黄色a级大片 | 日韩www. | 2025av在线播放 | 天堂网8| 亚洲春色在线观看 | 少妇高潮惨叫久久久久久 | 色老板精品凹凸在线视频观看 | 这里只有精品视频在线 | 欧美色拍 | 少妇高清精品毛片在线视频 | 可以免费观看av的网站 | 国内特级毛片 | 免费成人视屏 | 天天色一色 | 国产精品久久久久三级无码 | 久久99久久99 | 亚州黄色 | 亚洲精品免费在线播放 | 无码少妇精品一区二区免费动态 | 欧美日韩一区二区三区69堂 | 亚洲精品久久久久久 | 黄色特级一级片 | 第色| 久久精品性 | 天天插综合网 | 成人亚洲玉足脚交系列 | 视频一区欧美 | 国产精品探花在线观看 | 神马午夜不卡 | www视频免费观看 | 国产精品国产精品国产专区不卡 | 日本www在线| 欧洲黄色录像 | 久久午夜神器 | 韩国一级淫片免费看 | 偷拍欧美亚洲 | 国产一区二区三区免费 | 中文字幕人妻丝袜乱一区三区 | 久久美女av | 久久亚洲综合色图 | 午夜在线一区 | 成人久久免费视频 | 国产毛片欧美毛片久久久 | 无码精品国产一区二区三区免费 | 岛国精品| 狼人伊人av| 色播导航 | 香蕉视频污在线观看 | 日日噜噜噜噜人人爽亚洲精品 | 狠狠操在线观看 | 天天想你免费观看完整版高清电影 | 国产无遮挡又黄又爽免费视频 | 国产免费一区二区三区 | 黄网址在线观看 | 黄床大片 | 91精品国产91久久久久久吃药 | 7色av| 亚洲国产日韩欧美在线观看 | 67194少妇在线观看 | 女的高潮流时喷水图片大全 | 黄色av网| 性折磨bdsm欧美激情另类 | 乳色吐息在线观看 | 亚洲1页| 国产免费一区二区三区三州老师 | 久久久精品视频在线观看 | 国产欧美久久久久 | 99久久香蕉 | 欧美激情午夜 | 国产精品丝袜黑色高跟鞋的设计特点 | 亚洲午夜免费视频 | 亚洲六月婷婷 | 一级黄色美女视频 | 欧美老熟妇喷水 | 青青草91|