日韩性视频-久久久蜜桃-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)站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 色九月婷婷 | 日日操视频 | 国产精品呻吟久久 | 91不卡视频 | 欧美激情免费在线观看 | 在线播放视频高清在线观看 | 国产精品久久影视 | 花房姑娘免费观看全集 | 高hnp视频| 在线看片网站 | 影音先锋亚洲资源 | 搡老熟女国产 | 成人国产一区二区三区 | 电影寂寞少女免费观看 | 成人三级图片 | 欧美日韩午夜爽爽 | 在线播放第一页 | 长腿校花无力呻吟娇喘的视频 | 国产网红在线观看 | 国产精选一区 | av激情在线 | 亚洲AV无码一区二区三区性 | 免费h片网站 | 国产精品一区二区性色av | 精品无码久久久久成人漫画 | 老司机伊人 | 一区二区三区www污污污网站 | 国产精品三级 | av免费毛片 | 国产碰碰 | 久久精品这里 | 精品视频入口 | 精品一区二区三区久久久 | 欧美日本一本 | 日韩精品视频免费看 | 日韩精品免费一区二区夜夜嗨 | 香蕉网站在线观看 | 朝鲜女人性猛交 | 精品熟妇无码av免费久久 | 免费人成网| 五月天国产在线 | 国产毛片一区二区三区 | 在线欧美视频 | 男人的天堂2018 | av网在线 | 中文字幕在线观看二区 | 日韩美女视频网站 | 天天操天天操天天操天天操天天操 | 国模精品一区 | 奇米影视欧美 | 一级一级黄色片 | 亚洲第一欧美 | 很黄很污的视频 | 亚洲精品一线二线三线 | 国产人免费人成免费视频 | 蜜桃久久久久 | 免费av网站在线观看 | 久久手机免费视频 | 欧美草b| 午夜激情影视 | 四虎国产成人永久精品免费 | 国产乱淫片视频 | 亚欧美色图 | 精品人人人 | 尤物视频一区 | 在线v | 美女日批网站 | 国产精品va无码一区二区 | 欧美一区二区性久久久 | 91视频在线免费观看 | 亚洲欧美激情小说另类 | 欧美黑吊大战白妞 | 一二三四区视频 | 少妇人妻综合久久中文字幕 | 女同调教视频 | 久久精品日韩无码 | 国产成人无码精品久久二区三 | 天天干天天玩 | 深夜久久 | 久久综合色88 | 国产交换配乱淫视频免费 | 欧美丰满熟妇bbbbbb百度 | 欧美视频一区在线 | 啪啪导航 | 日韩av综合网 | 日本视频在线免费 | 日本h视频在线观看 | 射死你天天日 | 播播开心激情网 | 另类小说亚洲色图 | 最新最近中文字幕 | 欧美少妇视频 | 丝袜老师扒开让我了一夜漫画 | 欧美性色黄| 激情涩涩 | 蜜桃视频一区二区三区 | 国产成人一区二区三区小说 | 国产一级视频免费观看 | 黑人精品xxx一区一二区 |