Chinaunix首页 | 论坛 | 博客
  • 博客访问: 386092
  • 博文数量: 39
  • 博客积分: 1771
  • 博客等级: 上尉
  • 技术积分: 1231
  • 用 户 组: 普通用户
  • 注册时间: 2005-05-01 14:21
文章分类

全部博文(39)

文章存档

2013年(1)

2012年(4)

2011年(16)

2010年(6)

2009年(12)

分类: LINUX

2011-10-11 09:51:40

有个项目需要在两个进程间用condition variable作同步。我的打算是将condition variable和mutex放入shared memory,然后分别映射到两个进程的空间,然后就像两个线程同步一样的操作。但是实际操作下来发现老是出现segmentation fault。

后来仔细研究了一下pthreads的condition variable和mutex,发现他们默认是不支持两个进程间的共享的,只能使用在同一个进程的多个线程之间。如果要使用,必须使用
pthread_mutexattr_setpshared()
pthread_condattr_setpshared()
两个函数将condition variable和mutex设置成PTHREAD_PROCESS_SHARED属性(默认的是PTHREAD_PROCESS_PRIVATE 属性)。

以下是我的测试程序。一共3个文件。
common.h:
  1. #ifndef __COMMON_H
  2. #define __COMMON_H

  3. #include <sys/mman.h>
  4. #include <sys/stat.h> /* For mode constants */
  5. #include <fcntl.h>
  6. #include <unistd.h>
  7. #include <sys/types.h>
  8. #include <pthread.h>
  9. #include <stdio.h>

  10. //for shm_open()
  11. #define SHARE_PATH "/leonshm"
  12. #define SHARE_FLAG (O_RDWR | O_CREAT)
  13. #define SHARE_MODE (0660)
  14. //for ftruncate
  15. #define SHARE_LEN (1024)

  16. struct share_struct
  17. {
  18.     pthread_cond_t cond;
  19.     pthread_mutex_t mutex;
  20.     int data;
  21. };


  22. #endif //__COMMON_H
producer.c
  1. /* -*- compile-command: "gcc -o producer producer.c -lrt" -*- */
  2. /* set the data */
  3. #include "common.h"

  4. int
  5. main()
  6. {
  7.     int fd;
  8.     int i;
  9.     struct share_struct *shareinfo;

  10.     /* open posix shared memory */
  11.     fd = shm_open(SHARE_PATH, SHARE_FLAG, SHARE_MODE);
  12.     if (fd < 0) {
  13.         perror("shm_open");
  14.         return -1;
  15.     }
  16.     if (ftruncate(fd, SHARE_LEN) < 0) {
  17.         perror("ftruncate");
  18.         return -1;
  19.     }
  20.     /* map memory to process */
  21.     shareinfo = mmap(NULL, sizeof(struct share_struct), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
  22.     if (shareinfo < 0) {
  23.         perror("mmap");
  24.         return -1;
  25.     }
  26.     close(fd);

  27.     /* init struct */
  28.     /* by default, mutex and condition variable can not share between process, we have to enable this feature */
  29.     pthread_mutexattr_t mutexattr;
  30.     pthread_condattr_t condattr;
  31.     if (pthread_mutexattr_init(&mutexattr)) {
  32.         printf("error init mutex\n");
  33.         return -1;
  34.     }
  35.     //以下两个设置非常关键
  36.     if (pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED)) {
  37.         printf("error mutex set shared\n");
  38.         return -1;
  39.     }
  40.     if (pthread_condattr_init(&condattr)) {
  41.         printf("error init condition var\n");
  42.         return -1;
  43.     }
  44.     if (pthread_condattr_setpshared(&condattr, PTHREAD_PROCESS_SHARED)) {
  45.         printf("error condition set shared\n");
  46.         return -1;
  47.     }
  48.     shareinfo->data = 0;
  49.     pthread_mutex_init(&shareinfo->mutex, &mutexattr);
  50.     pthread_cond_init(&shareinfo->cond, &condattr);
  51.     
  52.     for (i = 1;; i++) {
  53.         pthread_mutex_lock(&shareinfo->mutex);
  54.         if (!shareinfo->data) {
  55.             shareinfo->data = i;
  56.             printf("producer, data set to:%d\n", shareinfo->data);
  57.         }
  58.         //printf("producer, running\n");
  59.         pthread_cond_broadcast(&shareinfo->cond);
  60.         pthread_mutex_unlock(&shareinfo->mutex);
  61.         //sleep(1);
  62.     }

  63.     if (shm_unlink(SHARE_PATH) < 0) {
  64.         perror("shm_unlink");
  65.         return -1;
  66.     }
  67.     pthread_mutexattr_destroy(&mutexattr);
  68.     pthread_condattr_destroy(&condattr);

  69.     return 0;
  70. }
consumer.c
  1. /* -*- compile-command: "gcc -o consumer consumer.c -lrt" -*- */
  2. /* clean the data */
  3. #include "common.h"

  4. int
  5. main()
  6. {
  7.     int fd;
  8.     struct share_struct *shareinfo;

  9.     /* open posix shared memory */
  10.     fd = shm_open(SHARE_PATH, SHARE_FLAG, SHARE_MODE);
  11.     if (fd < 0) {
  12.         perror("shm_open");
  13.         return -1;
  14.     }
  15.     if (ftruncate(fd, SHARE_LEN) < 0) {
  16.         perror("ftruncate");
  17.         return -1;
  18.     }
  19.     /* map memory to process */
  20.     shareinfo = mmap(NULL, sizeof(struct share_struct), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
  21.     if (shareinfo < 0) {
  22.         perror("mmap");
  23.         return -1;
  24.     }
  25.     close(fd);

  26.     while (1) {
  27.         pthread_mutex_lock(&shareinfo->mutex);
  28. #if 1
  29.         while (!shareinfo->data) {
  30. // printf("consumer, data:%d\n", shareinfo->data);
  31.             pthread_cond_wait(&shareinfo->cond, &shareinfo->mutex);
  32.         }
  33. #endif
  34.         printf("consumer, cleaning data:%d\n", shareinfo->data);
  35.         shareinfo->data = 0;
  36.         pthread_mutex_unlock(&shareinfo->mutex);
  37.         //sleep(1);
  38.     }
  39.     
  40.     if (shm_unlink(SHARE_PATH) < 0) {
  41.         perror("shm_unlink");
  42.         return -1;
  43.     }

  44.     return 0;
  45. }

编译成producer和consumer两个可执行文件后先运行producer,然后运行consumer,这两个进程就可以同步了。

阅读(3193) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~