您的当前位置:首页正文

Linux编程练习 --SystemV信号灯(信号量)

2023-03-06 来源:易榕旅网


Linux编程练习 --SystemV信号灯(信号量)

分类: Linux编程练习 2009-03-14 14:38 861人阅读 评论(0) 收藏 举报

1.综述

信号灯也可以说是一种锁,但它可以用来控制除了文件以外的更多资源。信号灯的初始值一般为一个正数,决定了可以分配的资源数,为进程分配一个资源后自减,减到0后被锁住。SysV IPC要求信号灯必须定义为一个集合。创建信号量时则指定此集合中的值。

双态信号灯是最简单的一种,0表示锁定,无资源;1表示解锁,有一个可用资源。

2.内核中与信号量有关的数据结构

内核中维持一份全局的struct semid_ds数组,semid_ds是信号量集合的结构。semget函数返回这个信号量集合在数组中的小标。

struct semid_ds

{

struct ipc_perm sem_perm; //该信号量集合的操作许可权限

struct sem *sem_base; //该数组的元素是:该集合包含的信号量的结构。

ushort sem_nsems; //sem_base数组的个数

time_t sem_otime; //最后一次成功修改该信号量数组的时间。

time_t sem_ctime; //成功创建的时间

};

struct sem

{

ushort semval; //信号量的当前值

short sempid; //最后一次返回该信号量的进程的id号

ushort semncnt; //等待semval大于当前值的进程的个数

ushort semzcnt; //等待semval变成0的进程的个数

};

3.信号灯操作

A.创建新信号量

int shmget(key_t key, int nsems, int flag); 返回值是信号量标示符。

key: key_t是int型的,这个是一个整数,要保证内核唯一性。

nsems:该集合包含的信号量的个数。

flag:创建的权限, 可以使一些读写权限与:IPC_CREAT ( | IPC_EXCL )的按位或。

当该函数成功时,linux内核中的semval值为0,但是该值的初始化没有可移植性(就是说不能保证所有系统都能初始化该值)

这个函数的作用:创建或者打开信号量集。

B.对一个已打开的信号量集的若干信号量操作控制

int semop(int semid, struct sembuf *opsptr, size_t nops);

semid:是semget返回的semid号。

nops:是数组opsptr的个数。

opsptr是操作结构的数组

struct sembuf

{

short sem_num; //信号量在semid集合中的序号:0到nsems - 1;

short sem_op; //操作

short sem_flag; //0, IPC_NOWAIT, SEM_UNDO

};

其中,sem_op值如下:semval为信号量当前值

a、如果sem_op大于0,表示sem_num信号量所代表的资源的释放,semval += sem_op;如果sem_flag指定了SEM_UNDO标志,则信号量的调整值减去sem_op;

b、如果sem_op小于0,表示sem_num信号量所代表资源的分配,具体是:如果semval 大于等于 sem_op的绝对值,则semval -= sem_op绝对值,成为新值;否则,阻塞知道条件满足,挂起(设IPC_NOWAIT会返回)

c、如果sem_op等于0,表示直到semval 等于0时才返回,否则一直挂起。

C.对信号量集实行控制操作

int semctl(int semid, int semnum, int cmd, ../* union semun arg */);

其中semid是信号量集合,semnum是信号在集合中的序号,

union semun

{

int val; /* cmd == SETVAL */

struct semid_ds *buf /* cmd == IPC_SET或者 cmd == IPC_STAT */

ushort *array; /* cmd == SETALL, 或 cmd = GETALL */

};

cmd是控制命令,参数可选

cmd取值如下:

GETVAL, SETVAL : semid集合中semnum信号量当前的semval值

GETALL,SETALL :semid集合中所有信号量的值。

IPC_RMID:删除semid信号量集

GETPID:返回最后成功操作该信号的进程号。

IPC_STAT:返回semid集合中的struct semid_ds结构。

下面练习熟悉system V信号量的操作,用system V实现多个进程的互斥

[cpp] view plaincopyprint?

1. /*sem.c*/

2. #include

3. #include

4. #include

5. #include

6. #include

7. #include

8. #include

9. int main (int argc, char **argv)

10. {

11. key_t ipckey;

12. int semid;

13. /*建立两个信号灯结构*/

14. struct sembuf sem[2]; /* sembuf defined in sys/sem.h */

15. /* 创建IPC Key */

16. ipckey = ftok(\"/tmp/foo\

17. /* 创建信号量. 4 == READ, 2 == ALTER */

18. semid = semget(ipckey, 1, 0666 | IPC_CREAT);

19. if (semid < 0)

20. {

21. printf(\"Error - %sn\

22. _exit(1);

23. }

24. /*设置*/

25. /* These never change so leave them outside the loop */

26. sem[0].sem_num = 0;

27. sem[1].sem_num = 0;

28. sem[0].sem_flg = SEM_UNDO; /* Release semaphore on exit */

29. sem[1].sem_flg = SEM_UNDO; /* Release semaphore on exit */

30. while(1)

31. {

32. printf(\"[%s] Waiting for the semaphore to be releasedn/n\

33. /* 设置两个信号灯,灯1等待,灯2请求资源锁 */

34. sem[0].sem_op = 0; /* Wait for zero */

35. sem[1].sem_op = 1; /* Add 1 to lock it*/

36. /*设置信号量集,两个信号量*/

37. semop(semid, sem, 2);

38. /*资源锁区*/

39. printf(\"[%s] I have the semaphoren/n\

40. sleep(rand() % 3); 41. /* Critical section, sleep for 0-2 seconds */ 42. sem[0].sem_op = -1; /* Decrement to unlock */ 43. /*出锁,对信号量1操作*/ 44. semop(semid, sem, 1); 45. printf(\"[%s] Released semaphoren/n\46. sleep(rand() % 3); /* Sleep 0-2 seconds */ 47. } 48. } /*sem.c*/#include #include #include #include #include #include #include int main (int argc, char **argv){key_t ipckey;int semid;/*建立两个信号灯结构*/struct sembuf sem[2]; /* sembuf defined in sys/sem.h *//* 创建IPC Key */ipckey = ftok(\"/tmp/foo\/* 创建信号量. 4 == READ, 2 == ALTER */semid = semget(ipckey, 1, 0666 | IPC_CREAT); 编译

然后运行时输入:

$ ./sem a & ./sem b &

结果如下:

[a] Waiting for the semaphore to be released

[a] I have the semaphore

[b] Waiting for the semaphore to be released

[a] Released semaphore

[b] I have the semaphore

[a] Waiting for the semaphore to be released

[b] Released semaphore

[a] I have the semaphore

[a] Released semaphore

[a] Waiting for the semaphore to be released

[a] I have the semaphore

因篇幅问题不能全部显示,请点此查看更多更全内容