<转>linux操作系统编程——共享内存读写(采用信号量进行同步互斥)

http://blog.csdn.net/yanghaoran321/article/details/7872722

程序要求:

     创建一个写端和一个读端,写端写入数据后读端才开始读,读端读完数据后,写端才可以开始写,这样的同步采用信号机制实现,并且写端与读端打开顺序不同也能实现功能;

程序如下:

(1)write.c(写端)

  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4. #include <sys/types.h>  
  5. #include <sys/ipc.h>  
  6. #include <sys/shm.h>  
  7. #include <errno.h>  
  8. #include "sem.h"  
  9.   
  10. typedef struct  
  11. {  
  12.     char buf[1024];  
  13. }memory;  
  14.   
  15. int main(int argc, const char *argv[])  
  16. {  
  17.     key_t key;  
  18.     memory *p = NULL;  
  19.     int shmid;  
  20.     int create_flag = 0;  
  21.     int sem_id;  
  22.   
  23.     if ((key = ftok("."'a')) < 0)  
  24.     {  
  25.         perror("failed to get key");  
  26.         exit(-1);  
  27.     }  
  28.   
  29.     if ((sem_id = semget(key, 1, 0666 | IPC_CREAT | IPC_EXCL)) < 0)  
  30.     {  
  31.         if (errno == EEXIST)  
  32.         {  
  33.             if ((sem_id = semget(key, 1, 0666)) < 0)  
  34.             {  
  35.                 perror("failed to semget");  
  36.                 exit(-1);  
  37.             }  
  38.         }  
  39.     }  
  40.   
  41.     init_sem(sem_id, 0);  
  42.   
  43.     if ((shmid = shmget(key, sizeof(memory), 0666 | IPC_CREAT | IPC_EXCL)) < 0)  
  44.     {  
  45.         if (errno == EEXIST)  
  46.         {         
  47.             if ((shmid = shmget(key, sizeof(memory), 0666)) < 0)  
  48.             {  
  49.                 perror("failed to shmget memory");  
  50.                 exit(-1);  
  51.             }  
  52.         }  
  53.         else  
  54.         {  
  55.             perror("failed to shmget");  
  56.             exit(-1);  
  57.         }  
  58.     }  
  59.     else   
  60.         create_flag = 1;  
  61.   
  62.     if ((p = shmat(shmid, NULL, 0)) == (void *)(-1))  
  63.     {  
  64.         perror("failed to shmat memory");  
  65.         exit(-1);  
  66.     }  
  67.   
  68.     while(1)  
  69.     {  
  70.         printf(">");  
  71.         fgets(p->buf, sizeof(p->buf), stdin);  
  72.         p->buf[strlen(p->buf) - 1] = 0;  
  73.   
  74.         sem_v(sem_id);  
  75.   
  76.         if (strncmp(p->buf, "quit", 4) == 0)  
  77.             break;  
  78.     }  
  79.   
  80.     if (create_flag == 1)  
  81.     {  
  82.         if (shmdt(p) < 0)  
  83.         {  
  84.             perror("failed to shmdt memory");  
  85.             exit(-1);  
  86.         }  
  87.   
  88.         if (shmctl(shmid, IPC_RMID, NULL) == -1)  
  89.         {     
  90.             perror("failed to delete share memory");  
  91.             exit(-1);  
  92.         }  
  93.   
  94.         delete_sem(sem_id);  
  95.     }  
  96.   
  97.     return 0;  
  98. }  

(2)read.c(读端)

  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4. #include <sys/types.h>  
  5. #include <sys/ipc.h>  
  6. #include <sys/shm.h>  
  7. #include <errno.h>  
  8. #include "sem.h"  
  9.   
  10. typedef struct  
  11. {  
  12.     char buf[1024];  
  13. }memory;  
  14.   
  15. int main(int argc, const char *argv[])  
  16. {  
  17.     key_t key;  
  18.     int shmid;  
  19.     memory *p = NULL;  
  20.     int create_flag = 0;  
  21.     int sem_id;  
  22.   
  23.     if ((key = ftok("."'a')) < 0)  
  24.     {  
  25.         perror("failed to get key");  
  26.         exit(-1);  
  27.     }  
  28.   
  29.     if ((sem_id = semget(key, 1, 0666 | IPC_CREAT | IPC_EXCL)) < 0)  
  30.     {  
  31.         if (errno == EEXIST)  
  32.         {  
  33.             if ((sem_id = semget(key, 1, 0666)) < 0)  
  34.             {  
  35.                 perror("failed to semget");  
  36.                 exit(-1);  
  37.             }  
  38.         }  
  39.     }  
  40.   
  41.     init_sem(sem_id, 0);  
  42.   
  43.     if ((shmid = shmget(key, sizeof(memory), 0666 | IPC_CREAT | IPC_EXCL)) < 0)  
  44.     {  
  45.         if (errno == EEXIST)  
  46.         {  
  47.             if ((shmid = shmget(key, sizeof(memory), 0666)) < 0)  
  48.             {  
  49.                 perror("failed to create share memory");  
  50.                 exit(-1);  
  51.             }  
  52.         }  
  53.         else  
  54.         {  
  55.             perror("failed to shmget");  
  56.             exit(-1);  
  57.         }  
  58.     }  
  59.     else  
  60.         create_flag = 1;  
  61.   
  62.     if ((p = shmat(shmid, NULL, 0)) == (void *)(-1))  
  63.     {  
  64.         perror("failed to shmat");  
  65.         exit(-1);  
  66.     }  
  67.       
  68.     while(1)  
  69.     {  
  70.         sem_p(sem_id);  
  71.   
  72.         if (strncmp(p->buf, "quit", 4) == 0)  
  73.             break;  
  74.   
  75.         printf("recv: %s ", p->buf);  
  76.   
  77.     }  
  78.   
  79.     if (create_flag == 1)  
  80.     {  
  81.         if (shmdt(p) < 0)  
  82.         {  
  83.             perror("failed to shmdt");  
  84.             exit(-1);  
  85.         }  
  86.   
  87.         if (shmctl(shmid, IPC_RMID, NULL) == -1)  
  88.         {  
  89.             perror("failed to delete share memory");  
  90.             exit(-1);  
  91.         }  
  92.   
  93.         delete_sem(sem_id);  
  94.     }  
  95.   
  96.     return 0;  
  97. }  

关于封装信号量函数的头文件:

  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <sys/types.h>  
  4. #include <sys/ipc.h>  
  5. #include <sys/sem.h>  
  6. #include <unistd.h>  
  7.   
  8. void init_sem(int , int );  
  9. void delete_sem(int );  
  10. void sem_p(int );  
  11. void sem_v(int );  
  12.   
  13. union semun  
  14. {  
  15.     int val;  
  16.     struct semid_ds *buf;  
  17.     unsigned short *array;  
  18. };  
  19.   
  20. void init_sem(int sem_id, int init_value)  
  21. {  
  22.     union semun sem_union;  
  23.   
  24.     sem_union.val = init_value;  
  25.   
  26.     if (semctl(sem_id, 0, SETVAL, sem_union) < 0)  
  27.     {  
  28.         perror("failed to init_sem");  
  29.         exit(-1);  
  30.     }  
  31.   
  32.     return ;  
  33. }  
  34.   
  35. void delete_sem(int sem_id)  
  36. {  
  37.     union semun sem_union;  
  38.   
  39.     if (semctl(sem_id, 0, IPC_RMID, sem_union) < 0)  
  40.     {  
  41.         perror("failed to delete_sem");  
  42.         exit(-1);  
  43.     }  
  44.   
  45.     return ;  
  46. }  
  47.   
  48. void sem_p(int sem_id)  
  49. {  
  50.     struct sembuf sem_b;  
  51.   
  52.     sem_b.sem_num = 0;  
  53.     sem_b.sem_op = -1;  
  54.     sem_b.sem_flg = SEM_UNDO;  
  55.   
  56.     if (semop(sem_id, &sem_b, 1) < 0)  
  57.     {  
  58.         perror("failed to sem_p");  
  59.         exit(-1);  
  60.     }  
  61.   
  62.     return;  
  63. }  
  64.   
  65. void sem_v(int sem_id)  
  66. {  
  67.     struct sembuf sem_b;  
  68.   
  69.     sem_b.sem_num = 0;  
  70.     sem_b.sem_op = 1;  
  71.     sem_b.sem_flg = SEM_UNDO;  
  72.   
  73.     if (semop(sem_id, &sem_b, 1) < 0)  
  74.     {  
  75.         perror("failed to sem_v");  
  76.         exit(-1);  
  77.     }  
  78.   
  79.     return ;  
  80. }  
原文地址:https://www.cnblogs.com/spinsoft/p/3335154.html