zoukankan      html  css  js  c++  java
  • <转>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. }  
  • 相关阅读:
    Python进阶: Decorator 装饰器你太美
    计算机网络自顶向下方法第3章-传输层 (Transport Layer).2
    Python进阶:值传递,引用传递?不存在的,是赋值传递
    Python进阶:对象复制与比较,分深浅,见真假
    Python基础:模块化来搭项目
    这说明一个问题
    我稍微思考了一下
    由LruCache和DiskLruCache提供三级缓存支持的ImageLoader
    回忆一个加塞方法
    三年六班的李子明同学,你妈拿了两本计算机基础在二号树上等你
  • 原文地址:https://www.cnblogs.com/spinsoft/p/3335154.html
Copyright © 2011-2022 走看看