Chinaunix首页 | 论坛 | 博客
  • 博客访问: 83072
  • 博文数量: 18
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 85
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-18 09:53
文章分类
文章存档

2015年(18)

我的朋友

分类: LINUX

2015-05-13 18:05:09

信号量实现进程间访问互斥的资源测试例子。
主要涉及到的函数及原型如下(加粗、颜色表示要重点关心的上下文相关变量)
1: key_tftok(char *fileName, int id);//目的获取key值

2: intsemget(key_t key, int nsems, int semflg)//目的获取id

3:int semctl(int semid, int semnum, int cmd, union semunarg)//目的设置信号量的值,获取信号量的值等等,功能通过cmd变量控制
//其中semunarg必须由用户自身定义,格式如下
  1. union semun {
  2.     int val;
  3.     struct semid_ds *buf;
  4.     unsigned short *array;
  5.     struct seminfo *__buf;
  6.     //other linux specific
  7. };

4: int semop(int semid, struct sembuf *sops, unsign ednsops)//目的改变信号量的值,在sembuf中。

可通过每个函数大体功能,man手册中查找一些说明,进行研究测试。
以下测试代码非常简单,仅仅是为了熟悉api的基本功能,如果有错误和需要说明的地方,欢迎指正。

点击(此处)折叠或打开

  1. #include <sys/types.h>
  2. #include <sys/sem.h>
  3. #include <stdio.h>
  4. #include <errno.h>
  5. #include <sys/shm.h>
  6. #include <stdlib.h>
  7. #include <unistd.h>

  8. union semun {//semctl函数的第三个参数结构定义,现只关心设置val,其它成员可忽视,起到初始化资源数目的作用
  9.     int val;
  10.     // struct semid_ds *buf;
  11.     // unsigned short *array;
  12.     // struct seminfo *__buf;
  13. };

  14. int sem_init(int semid, int initval)//初始化信号量 init val
  15. {
  16.     union semun arg;

  17.     arg.val = initval;
  18.     semctl(semid, 0, SETVAL, arg);//SETVAL 是semctl的cmd参数,意思是设置信号量为arg.val的值,0是信号量中第1个资源的下标
  19.     //fixme if some error
  20.     return 0;
  21. }

  22. int creat_sem(char *fileName)//创建一个信号灯,信号量默认写了1个,如果没有该信号量,创建,如果有,获取id
  23. {
  24.     int id;
  25.     key_t key;

  26.     key = ftok(fileName, 1);
  27.     if (key < 0) {
  28.         perror("ftok()");
  29.         key = 5;//any number just for test
  30.     }

  31.     if ((id = semget(key, 1, IPC_CREAT | IPC_EXCL |0660)) < 0) {//1个信号量 creat? or exist?
  32.         if ((id = semget(key, 1, IPC_CREAT | 0660)) < 0) {//1个信号量 if exist,only get the id
  33.             printf("semget error: id = %d\n", id);
  34.         }
  35.         printf("sem allready exist: id = %d\n", id);
  36.     } else {//init the number when first use
  37.         sem_init(id, 0);
  38.     }

  39.     return id;
  40. }

  41. void P(int semid)//申请资源,资源数sembuf中的sem_op - 1
  42. {
  43.     int ret = 0;
  44.     struct sembuf sb;
  45.     sb.sem_num = 0;
  46.     sb.sem_op = -1;
  47.     sb.sem_flg = 0;

  48.     ret = semop(semid, &sb, 1);
  49.     if (ret < 0) {
  50.         printf("error in p(s)\n");
  51.     }
  52. }

  53. void V(int semid)//释放资源,资源数sembuf中的sem_op - 1
  54. {
  55.     int ret = 0;
  56.     struct sembuf sb;
  57.     sb.sem_num = 0;
  58.     sb.sem_op = 1;
  59.     sb.sem_flg = 0;

  60.     ret = semop(semid, &sb, 1);
  61.     if (ret < 0) {
  62.         printf("error in v(s)\n");
  63.     }
  64. }

  65. void showStat(int semid)
  66. {
  67.     int ret = semctl(semid, 0, GETVAL, 0);

  68.     printf("now %d val is %d\n", semid, ret);
  69. }

  70. int main(int argc, char **argv)
  71. {
  72.     int sem_id0, sem_id1;

  73.     if (fork() == 0) {//子进程 进程1
  74.         sem_id0 = creat_sem("/tmp/2");
  75.         sem_id1 = creat_sem("/tmp/3");
  76.         V(sem_id1);
  77.         while (1) {
  78.             P(sem_id0);
  79.             printf("working : process11111\n");
  80.             showStat(sem_id0);
  81.             showStat(sem_id1);
  82.             sleep(1);
  83.             V(sem_id1);
  84.         }
  85.     } else {//父进程 进程2
  86.         sem_id0 = creat_sem("/tmp/2");
  87.         sem_id1 = creat_sem("/tmp/3");
  88.         sleep(2);
  89.         while (1) {
  90.             P(sem_id1);
  91.             printf("working : process2222222222\n");
  92.             showStat(sem_id0);
  93.             showStat(sem_id1);
  94.             sleep(2);
  95.             V(sem_id0);
  96.         }
  97.     }

  98.     return 0;
  99. }
阅读(2188) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~