Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1045577
  • 博文数量: 573
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 66
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-28 16:21
文章分类

全部博文(573)

文章存档

2018年(3)

2016年(48)

2015年(522)

分类: LINUX

2015-12-02 15:22:29

semaphore.c文件

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <sys/sem.h>
  5. #include <sys/types.h>
  6. #include <sys/ipc.h>
  7. #include <sys/types.h>
  8. #include <fcntl.h>
  9. #include <sys/stat.h>

  10. #define IPCKEY 0x14

  11. /*
  12. man semctl函数可知:
  13. When there are four, the fourth has the type union semun.
  14. The calling program must define this union as
  15. follows:
  16. 所以这个联合结构的定义:必须手工加上去,
  17. 否则编译器会报错:不知道union semun存储空间的大小。
  18. */
  19. typedef union semun
  20. {
  21.         int val;
  22.         struct semid_ds * buf;
  23.         unsigned short * array;
  24.         struct seminfo * __buf;
  25. }MYSEM;


  26. /*
  27. 功能:编写2个进程,1个信号量集合,集合中有2个信号量,1个进程 semaphore 从键盘输入数据,
  28.             再写进文件,之后,才释放信号量资源,另外1个进程 semaphore2 才容许从文件中读取数据,
  29.             之后,才容许第1个进程 semaphore 可以再次从键盘输入数据。
  30.             
  31.             这样可以保证:进程 semaphore2 在文件中有数据的时候,才会进去读取。
  32. 注意:
  33.             进程 semaphore2 必须先执行,如果 进程 semaphore 先执行,将会出现死锁。这个问题已经解决了。
  34. */
  35. int main(int argc, char * * argv)
  36. {
  37.         printf("1个信号量集合,集合中有2个信号量。都作2元信号量,控制单个资源,被用作一个锁机制。\n");
  38.         printf("0号 信号量:可写,没有进程在读取文件了,可以向文件中写数据了。\n");
  39.         printf("1号 信号量:可读,表示没有进程在写文件了,可以从文件中读取数据了。\n");
  40.     
  41.         int ret;
  42.         int fd;
  43.         fd = open("./sem.txt", O_WRONLY|O_TRUNC);
  44.         if(fd < 0)
  45.         {
  46.                 printf("open err!\n");
  47.                 exit(-1);
  48.         }
  49.     
  50.         char path[1024];
  51.         memset(path, 0, sizeof(path));
  52.         strcpy(path, "/etc/hosts");
  53.         printf("path=[%s]\n", path);

  54.         key_t key = 0;
  55.         printf("key=[%x]\n", key);
  56.         /*path必须是已经存在的文件名,将path文件的索引节点号取出,
  57.         前面加上子序号IPCKEY,得到key_t的返回值。
  58.         功能:可以保证两个不同用户下的两组相同程序获得互不干扰的IPC键值
  59.         */
  60.         key = ftok(path, IPCKEY);
  61.         if(key < 0)
  62.         {
  63.                 printf("ftok err!\n");
  64.                 exit(-1);
  65.         }
  66.         printf("key=[%x]\n", key);
  67.         
  68.         int semid;
  69.         /*semget 功能:创建信号量集合,该集合中信号量数为2个*/
  70.         semid = semget(key, 2, IPC_CREAT|0777);
  71.         if(semid < 0)
  72.         {
  73.                 printf("semget err!\n");
  74.                 exit(-1);
  75.         }
  76.         printf("semid=[%d]\n", semid);
  77.         
  78.         MYSEM sem; /*多个特定命令参数的联合*/
  79.         sem.val = 1; /*信号量初始值为1:称为二元信号量,它控制单个资源。*/
  80.         /*semctl SETVAL 功能:设置信号量集合中 信号量成员0 的信号量初始值。
  81.         下面一句也可以是:semctl(semid, 0, SETVAL, 1);*/
  82.         ret = semctl(semid, 0, SETVAL, sem);
  83.         if(ret < 0)
  84.         {
  85.                 printf("semctl err!\n");
  86.                 exit(-1);
  87.         }
  88.         
  89.         sem.val = 0; /*信号量初始值为0*/
  90.         ret = semctl(semid, 1, SETVAL, sem);
  91.         if(ret < 0)
  92.         {
  93.                 printf("semctl err!\n");
  94.                 exit(-1);
  95.         }
  96.         
  97.         struct semid_ds semds; /*每一个信号量集合,都有这样一个结构体*/
  98.         sem.buf = &semds;
  99.         ret = semctl(semid, 0, IPC_STAT, sem);
  100.         printf("信号量集合 的属性如下:\n");
  101.         if(ret < 0)
  102.         {
  103.                 printf("semctl err!\n");
  104.                 exit(-1);
  105.         }
  106.         printf("信号量集合中,有[%d]个信号量\n", semds.sem_nsems);
  107.         printf("最后一次对信号量集合操作(semop)的时间=[%s]\n", ctime(&(semds.sem_otime)));
  108.         printf("最后一次对信号量集合修改的时间=[%s]\n", ctime(&(semds.sem_ctime)));
  109.         
  110.         
  111.         /*semctl GETVAL 功能:取得信号量集合中 0号 信号量 的当前信号值。*/
  112.         ret = semctl(semid, 0, GETVAL);
  113.         printf("0号 信号量 的当前信号值=[%d]\n", ret);
  114.         if(ret < 0)
  115.         {
  116.                 printf("semctl err!\n");
  117.                 exit(-1);
  118.         }
  119.         
  120.         /*semctl GETVAL 功能:取得信号量集合中 1号 信号量 的当前信号值。*/
  121.         ret = semctl(semid, 1, GETVAL);
  122.         printf("1号 信号量 的当前信号值=[%d]\n", ret);
  123.         if(ret < 0)
  124.         {
  125.                 printf("semctl err!\n");
  126.                 exit(-1);
  127.         }
  128.         
  129.         struct sembuf sops[2]; /*信号量操作数组*/
  130.         char buf[1024];
  131.         while(1)
  132.         {
  133.                 sops[0].sem_num = 0; /*0号 信号量*/
  134.                 sops[0].sem_op = -1; /*操作:负:表示要获取由 0号 信号量 控制的资源。*/
  135.                 sops[0].sem_flg = SEM_UNDO; /*sem_op的绝对值 加到该进程的 0号 信号量 的调整值上。*/
  136.                 printf("0号 信号量 减 1 操作:开始执行 semop 函数:\n");
  137.                 /*semop功能:对 0号 信号量 执行减 1 操作,即想获取资源。
  138.                 分析:第一次时:由于0号 信号量 初始值是1,表示资源可用,semop函数不会阻塞。
  139.                 如果 0号 信号量 的值已经是0了,则想再做减1操作的时候,semop函数会阻塞。*/
  140.                 ret = semop(semid, &sops[0], 1);
  141.                 printf("semop ret = [%d]\n", ret);
  142.                 if(ret < 0)
  143.                 {
  144.                         printf("semop err!\n");
  145.                         exit(-1);
  146.                 }
  147.                 
  148.                 /*semctl GETVAL 功能:取得信号量集合中 0号 信号量 的当前信号值。*/
  149.                 ret = semctl(semid, 0, GETVAL);
  150.                 printf("0号 信号量 的当前信号值=[%d]\n", ret);
  151.                 if(ret < 0)
  152.                 {
  153.                         printf("semctl err!\n");
  154.                         exit(-1);
  155.                 }
  156.                 
  157.                 memset(buf, 0, sizeof(buf));
  158.                 printf("input:\n");
  159.                 ret = read(0, buf, sizeof(buf));
  160.                 if(ret < 0)
  161.                 {
  162.                         printf("read err!\n");
  163.                         exit(-1);
  164.                 }
  165.                 lseek(fd, 0, SEEK_SET);
  166.                 printf("read buf = [%s], ret = [%d]\n", buf, ret);
  167.                 ret = write(fd, buf, ret); /*将从键盘输入的数据,保存到文件中*/
  168.                 if(ret < 0)
  169.                 {
  170.                         printf("write err!\n");
  171.                         exit(-1);
  172.                 }
  173.                 
  174.                 sops[1].sem_num = 1; /*1号 信号量*/
  175.                 sops[1].sem_op = 1; /*操作:正:表示要释放由 1号 信号量 控制的资源。*/
  176.                 sops[1].sem_flg = SEM_UNDO; /*sem_op的绝对值 加到该进程的 1号 信号量 的调整值上。*/
  177.                 printf("1号 信号量 加 1 操作:执行 semop 函数:\n");
  178.                 /*semop功能:对 1号 信号量 执行加 1 操作,即想释放资源, semop函数不会阻塞。*/
  179.                 ret = semop(semid, &sops[1], 1);
  180.                 printf("semop ret = [%d]\n", ret);
  181.                 if(ret < 0)
  182.                 {
  183.                         printf("semop err!\n");
  184.                         exit(-1);
  185.                 }
  186.         }
  187.         
  188.         /*semctl IPC_RMID功能:删除 系统中的信号集合semid*/
  189.         ret = semctl(semid, 0, IPC_RMID);
  190.         if(ret < 0)
  191.         {
  192.                 printf("semctl err!\n");
  193.                 exit(-1);
  194.         }
  195.         
  196.         return 0;
  197. }
semaphore2.c

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <sys/sem.h>
  5. #include <sys/types.h>
  6. #include <sys/ipc.h>
  7. #include <sys/types.h>
  8. #include <fcntl.h>
  9. #include <sys/stat.h>

  10. #define IPCKEY 0x14

  11. typedef union semum
  12. {
  13.         int val;
  14.         struct semid_ds * buf;
  15.         unsigned short * array;
  16. }MYSEM;

  17. int main(int argc, char * * argv)
  18. {
  19.         int ret;
  20.         int fd;
  21.         fd = open("./sem.txt", O_RDONLY);
  22.         if(fd < 0)
  23.         {
  24.                 printf("open err!\n");
  25.                 exit(-1);
  26.         }

  27.         char path[1024];
  28.         memset(path, 0, sizeof(path));
  29.         strcpy(path, "/etc/hosts");
  30.         printf("path=[%s]\n", path);

  31.         key_t key = 0;
  32.         printf("key=[%x]\n", key);
  33.         /*path必须是已经存在的文件名,将path文件的索引节点号取出,
  34.         前面加上子序号IPCKEY,得到key_t的返回值。
  35.         功能:可以保证两个不同用户下的两组相同程序获得互不干扰的IPC键值
  36.         */
  37.         key = ftok(path, IPCKEY);
  38.         if(key < 0)
  39.         {
  40.                 printf("ftok err!\n");
  41.                 exit(-1);
  42.         }
  43.         printf("key=[%x]\n", key);
  44.         
  45.         int semid;
  46.         /*semget 功能:创建信号量集合,该集合中信号量数为2个。
  47.         如果集合已经存在:则第2个参数将被忽略。*/
  48.         semid = semget(key, 2, 0);
  49.         if(semid < 0)
  50.         {
  51.                 printf("semget err!\n");
  52.                 exit(-1);
  53.         }
  54.         printf("semid=[%d]\n", semid);
  55.         
  56.         /*
  57.         MYSEM sem;
  58.         sem.val = 0;
  59.         ret = semctl(semid, 1, SETVAL, sem);
  60.         if(ret < 0)
  61.         {
  62.                 printf("semctl err!\n");
  63.                 exit(-1);
  64.         }
  65.         */
  66.         
  67.         /*semctl GETVAL 功能:取得信号量集合中 1号 信号量 的当前信号值。*/
  68.         ret = semctl(semid, 1, GETVAL);
  69.         printf("1号 信号量 的当前信号值=[%d]\n", ret);
  70.         if(ret < 0)
  71.         {
  72.                 printf("semctl err!\n");
  73.                 exit(-1);
  74.         }
  75.         
  76.         struct sembuf sops[2]; /*信号量操作数组*/
  77.         char buf[1024];
  78.         while(1)
  79.         {
  80.                 sops[1].sem_num = 1; /*1号 信号量*/
  81.                 sops[1].sem_op = -1; /*操作:负:表示要申请获取由 1号 信号量 控制的资源。*/
  82.                 sops[1].sem_flg = SEM_UNDO; /*sem_op的绝对值 加到该进程的 1号 信号量 的调整值上。*/
  83.                 printf("1号 信号量 减 1 操作:开始执行 semop 函数:\n");
  84.                 /*semop功能:对 1号 信号量 执行减 1 操作,即想获取资源。
  85.                 分析:第一次时:由于1号 信号量 初始值是0,表示无资源可用,semop函数会阻塞,
  86.                 直到 semaphore 进程 给 1号 信号量 进行 加 1 操作,进程才向下继续执行。
  87.                 如果 1号 信号量 的值已经是1了,则想再做减1操作的时候,semop函数不会阻塞。*/
  88.                 ret = semop(semid, &sops[1], 1);
  89.                 printf("semop ret = [%d]\n", ret);
  90.                 if(ret < 0)
  91.                 {
  92.                         printf("semop err!\n");
  93.                         exit(-1);
  94.                 }
  95.                 
  96.                 /*semctl GETVAL 功能:取得信号量集合中 0号 信号量 的当前信号值。*/
  97.                 ret = semctl(semid, 1, GETVAL);
  98.                 printf("1号 信号量 的当前信号值=[%d]\n", ret);
  99.                 if(ret < 0)
  100.                 {
  101.                         printf("semctl err!\n");
  102.                         exit(-1);
  103.                 }
  104.                 
  105.                 lseek(fd, 0, SEEK_SET);
  106.                 memset(buf, 0, sizeof(buf));
  107.                 ret = read(fd, buf, sizeof(buf));
  108.                 if(ret < 0)
  109.                 {
  110.                         printf("read err!\n");
  111.                         exit(-1);
  112.                 }
  113.                 printf("read buf = [%s], ret = [%d]\n", buf, ret);
  114.                 
  115.                 sops[0].sem_num = 0; /*0号 信号量*/
  116.                 sops[0].sem_op = 1; /*操作:正:表示要释放由 0号 信号量 控制的资源。*/
  117.                 sops[0].sem_flg = SEM_UNDO; /*sem_op的绝对值 加到该进程的 0号 信号量 的调整值上。*/
  118.                 printf("0号 信号量 加 1 操作:执行 semop 函数:\n");
  119.                 /*semop功能:对 0号 信号量 执行加 1 操作,即想释放资源, semop函数不会阻塞。*/
  120.                 ret = semop(semid, &sops[0], 1);
  121.                 printf("semop ret = [%d]\n", ret);
  122.                 if(ret < 0)
  123.                 {
  124.                         printf("semop err!\n");
  125.                         exit(-1);
  126.                 }
  127.         }
  128.         
  129.         /*semctl IPC_RMID功能:删除 系统中的信号集合semid*/
  130.         ret = semctl(semid, 0, IPC_RMID);
  131.         if(ret < 0)
  132.         {
  133.                 printf("semctl err!\n");
  134.                 exit(-1);
  135.         }
  136.         
  137.         return 0;
  138. }


阅读(889) | 评论(0) | 转发(0) |
0

上一篇:消息队列

下一篇:共享内存

给主人留下些什么吧!~~