Chinaunix首页 | 论坛 | 博客
  • 博客访问: 106648
  • 博文数量: 50
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 583
  • 用 户 组: 普通用户
  • 注册时间: 2012-08-12 14:38
文章分类

全部博文(50)

文章存档

2013年(50)

我的朋友

分类: LINUX

2013-03-30 23:49:05

      互斥量(mutex)可以解决多线程间对共有数据访问时的资源竞争问题,但是mutex只能在线程间使用,为解决进程间对共有资源的访问,可以使用信号量semaphore替代mutex,以下例程fence.c程序用semaphore实现了多进程对公共资源的同时访问,通过信号量实现了栅栏效应。
      信号量是一个整数数组,程序中共使用7个信号量,第0-5个信号量用于控制子进程输出数字(1号子进程输出1,2号子进程输出2,...),第6个信号量用于通知父进程子进程已输出完成,并且
一直等最慢的子进程完成了,父进程才能再次释放1次0-5个信号量,父进程累计释放6次,每个子进程输出6次。

点击(此处)折叠或打开

  1. /*栅栏效应,父进程等5个子进程中运行最慢的子进程释放资源后,才会再一次释放信号量,让子进程再次工作*/
  2. #include <sys/types.h>
  3. #include <sys/ipc.h>
  4. #include <sys/sem.h>
  5. #include <sys/wait.h>
  6. #include <unistd.h>

  7. #include <stdio.h>
  8. #include <stdlib.h>

  9. #define CHILD_NR 6
  10. #define SEM_NUM (CHILD +1)
  11. static void child(int semid, int num)
  12. {
  13.   struct sembuf my_buf, p_buf;
  14.   int i;
  15.   int seconds;

  16.   srand(getpid());

  17.   p_buf.sem_num = CHILD_NR;
  18.   p_buf.sem_op = 1;
  19.   p_buf.sem_flg = 0;

  20.   my_buf.sem_num = num;
  21.   my_buf.sem_op = -1;
  22.   my_buf.sem_flg = 0;
  23.   for (i = 0; i < 5; i++) {
  24.     semop(semid, &my_buf, 1); /*等待父进程释放第m个信号量,获得信号量前处于阻塞状态*/

  25.     seconds = (unsigned)rand() % 4 + 1; /*模拟子进程的运行*/
  26.     sleep(seconds);
  27.     printf("%d ", num + 1);
  28.     fflush(NULL);

  29.     semop(semid, &p_buf, 1); /*释放第7个信号量,6个子进程退出后,父进程将获得第7个信号量的控制权*/
  30.   }

  31.   return;
  32. }
  33. int main(void)
  34. {
  35.   pid_t pid;
  36.   int semid;
  37.   struct sembuf my_buf, child_buf[CHILD_NR];/*信号量操作由sembuf结构体数组决定*/
  int i;
  1.   unsigned short arr[CHILD_NR + 1] = { /*用于初始化信号量,信号量是一个整形数组*/
  2.     [CHILD_NR] = CHILD_NR,
  3.   };

  4.   semid = semget(IPC_PRIVATE, CHILD_NR + 1, IPC_CREAT | 0600);
  5.   /*创建信号量集*/
  6.   if (semid == -1) {
  7.     perror("semget()");
  8.     return 1;
  9.   }

  10.   semctl(semid, 0, SETALL, arr);
  11.   /*初始化信号量集*/

  12.   for (i = 0; i < CHILD_NR; i++) {
  13.     pid = fork(); /*创建CHILD_NR个子进程*/
  14.     /* if error */
  15.     if (pid == 0) {
  16.       child(semid, i);
  17.       return 0;
  18.     }
  19.   }
  20.     /*初始化信号操作结构体数组*/
  21.   for (i = 0; i < CHILD_NR; i++) {
  22.     child_buf[i].sem_num = i;
  23.     child_buf[i].sem_op = 1;
  24.     child_buf[i].sem_flg = 0;
  25.   }
  26.   my_buf.sem_num = CHILD_NR;
  27.   my_buf.sem_op = -CHILD_NR;
  28.   my_buf.sem_flg = 0;

  29. #if 0
  30.   /* debug */
  31.   int val;
  32.   val = semctl(semid, CHILD_NR, GETVAL);
  33.   if (val == -1) {
  34.     perror("semctl(GETVAL)");
  35.   }
  36.   printf("debug: sem[%d] = %d\n", CHILD_NR,val);/*打印信号量的值j*/
  37. #endif
  38.   for (i = 0; i < 5; i++) {
  39.     semop(semid, &my_buf, 1); /*获取第7个信号量控制的资源*/
  40.     printf("\n");

  41.     semop(semid, child_buf,CHILD_NR);/*释放第0-5个信号量控制的资源*/
  42.   }
  43.   semop(semid, &my_buf, 1);
  44.   /*等待子进程最后一次释放完资源后,再输出一次回车*/
  45.   printf("\n");

  46.   semctl(semid, 0, IPC_RMID); /*删除信号量集合*/
  47.   for (i = 0; i < CHILD_NR; i++) {
  48.     wait(NULL); /*收尸*/
  49.   }

  50.   return 0;
  51. }


阅读(1308) | 评论(2) | 转发(1) |
0

上一篇:懒人专用Makefile

下一篇:LINUX心得体会

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

setagllib2013-04-02 09:14:26

楼主,不好意思,俺理解错了,程序没有问题。

setagllib2013-04-01 17:40:57

子进程函数child里,为何使用一个for循环呀,楼主?1号进程是不是打印数字1共5次,总共30次呢