|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
& @. F7 [* W5 {& H! j) Y1 i8 ?( y
信号量又称为信号灯,它是用来协调不同进程间的数据对象的,而最主要的应用是前一节的共享内存方式的进程间通信。本质上,信号量是一个计数器,它用来记录对某个资源(如共享内存)的存取状况。一般说来,为了获得共享资源,进程需要执行下列操作:
9 F* J; y: p% G `9 m" \+ @+ `1 Q( A* _/ P/ M; O+ Z! h3 O
(1) 测试控制该资源的信号量。' K" G9 D/ e* N
7 _- b1 J% c: E# ~. a3 k, [8 i(2) 若此信号量的值为正,则允许进行使用该资源。进程将进号量减1。
5 E- F# r4 q8 G1 j1 ?: m5 K+ c: {
(3) 若此信号量为0,则该资源目前不可用,进程进入睡眠状态,直至信号量值大于0,进程被唤醒,转入步骤(1)。
8 a/ O, N7 |$ M o0 v
9 N Z" @4 h) B! ^9 U& }/ _(4) 当进程不再使用一个信号量控制的资源时,信号量值加1。如果此时有进程正在睡眠等待此信号量,则唤醒此进程。& C! M/ ?6 x0 f
+ {' v) [8 [2 C) U# L; l
维护信号量状态的是Linux内核操作系统而不是用户进程。我们可以从头文件/usr/src/linux/include /linux /sem.h中看到内核用来维护信号量状态的各个结构的定义。信号量是一个数据集合,用户可以单独使用这一集合的每个元素。要调用的第一个函数是semget,用以获得一个信号量ID。. X3 h% [7 G0 T
% J# B9 q5 ^3 l- O2 V1 C6 y1 ^#i nclude <sys/types.h>
) `2 U3 ]: v! A* J% k7 y8 H" j! U4 f #i nclude <sys/ipc.h>
U/ H3 @ X& ]# }6 G# E6 t #i nclude <sys/sem.h>, Y }0 H; I! \0 D
int semget(key_t key, int nsems, int flag);
" S6 {8 a7 p4 b0 |2 ~7 H \5 @4 n2 X+ Q) F( g9 r8 {1 [
key是前面讲过的IPC结构的关键字,它将来决定是创建新的信号量集合,还是引用一个现有的信号量集合。nsems是该集合中的信号量数。如果是创建新集合(一般在服务器中),则必须指定nsems;如果是引用一个现有的信号量集合(一般在客户机中)则将nsems指定为0。
5 Y5 N3 ~6 r* A6 m3 Z
3 P3 O7 W* o' y. w4 ~+ }sEMCtl函数用来对信号量进行操作。) c8 w+ `( E3 [" v& u# f' e
2 I" |2 o1 ~( R( G) Bint semctl(int semid, int semnum, int cmd, union semun arg);9 X9 d8 `/ _6 q/ ]
3 s' W3 ]' g, b, K不同的操作是通过cmd参数来实现的,在头文件sem.h中定义了7种不同的操作,实际编程时可以参照使用。. q/ K# ^8 V& }9 Z; f8 ]6 n5 M
1 t: F P$ S0 k0 T! q9 X& K
semop函数自动执行信号量集合上的操作数组。0 s1 r# k' s. s& e! R* s
4 k$ i: _) H! n' S8 A1 n0 X
int semop(int semid, struct sembuf semoparray[], size_t nops);
, @8 M4 `, S( `7 ] D3 d
" |: q* _4 V) h3 c! fsemoparray是一个指针,它指向一个信号量操作数组。nops规定该数组中操作的数量。: M4 Y8 C7 k Y# I6 Y" g, j( D4 n
! F9 q8 h5 }; i5 m* A
例:获取信号量状态:
4 Q! A# i- ^5 w' d+ x( `7 v5 t6 n1 G& ?# e2 H O' C
struct semid_ds semidbuf;, e W, E* j3 `) v0 Q0 \- {
u9 o7 R0 o4 a& Usemctl(semid, 0, IPC_STAT, &semidbuf); |
|