进程间通信:用信号量实现对共享内存读写顺序的控制

这本是一道题:一本是一个全局变量来做的控制共享内存通信方式,一个已经实现的信号量通信,最终的结果是让这两个掺和在一起。用信号量来控制共享内存通信的读写顺序。

            原本信号量通信方式的函数在这是,原本的共享内存程序在这里。

            做的最新的结果是可以通信了,但是在客户端有一点点异常,就是在服务器端还没有释放信号量,但是客户端不可以获取的,这使我很疑惑。

服务器端:

  1. #include <unistd.h>   
  2. #include <stdlib.h>   
  3. #include <stdio.h>   
  4. #include <string.h>   
  5. #include <sys/types.h>   
  6. #include <sys/ipc.h>   
  7. #include <sys/shm.h>   
  8. #include "shm_com.h"   
  9.   
  10. #include <sys/sem.h>   
  11.   
  12. #include <signal.h>   
  13. /********************************************************/  
  14. int pid,semid;  
  15. /********************************************************/  
  16.   
  17. void my_func(int sign_no)  
  18. {  
  19.     if(sign_no==SIGINT)  
  20.     {  
  21.         printf("\nYes Sir,I have get SIGINT\n");  
  22.         if(semctl(semid, 0, IPC_RMID, 0)<0)  
  23.         {  
  24.             printf("semctl remove semaphore set failed\n");  
  25.             exit(EXIT_FAILURE);  
  26.         }  
  27.         printf("semctl remove semaphore set OK\n");  
  28.         exit(EXIT_FAILURE);  
  29.     }  
  30. }  
  31.   
  32. int main(void)  
  33. {  
  34.     int running=1;  
  35.     void *shared_memory=(void *)0;  
  36.     struct shared_use_st *shared_stuff;  
  37.     char buffer[BUFSIZ];  
  38.     int shmid;  
  39.   
  40.     signal(SIGINT, my_func);  
  41.   
  42. /***************************************************************/     
  43.       
  44.     key_t semkey;  
  45.     if((semkey=ftok("/home", 1))<0)  
  46.     {  
  47.         printf("ftok failed\n");  
  48.         exit(EXIT_FAILURE);  
  49.     }  
  50.     printf("ftok ok, semkey=%d\n", semkey);  
  51.       
  52.     if((semid=semget(semkey, 1, IPC_CREAT|0666))<0)  
  53.     {  
  54.         printf("semget failed\n");  
  55.         exit(EXIT_FAILURE);  
  56.     }  
  57.     printf("semget ok, semid = %d\n", semid);  
  58.       
  59.     if((semctl(semid, 0, SETVAL, 1))<0)  
  60.     {  
  61.         printf("semctl set sermval failed\n");  
  62.         exit(EXIT_FAILURE);  
  63.     }  
  64.     printf("semctl set semval ok\n");  
  65.       
  66.     struct sembuf p_op_buf, v_op_buf;  
  67.     p_op_buf.sem_num=0;  
  68.     p_op_buf.sem_op = -1;  
  69.       
  70. /******************************************************************/  
  71.   
  72.     /*创建共享内存*/  
  73.     shmid=shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);  
  74.     if(shmid==-1)  
  75.     {  
  76.         fprintf(stderr,"shmget failed\n");  
  77.         exit(EXIT_FAILURE);  
  78.     }  
  79.   
  80.     /*映射共享内存*/  
  81.     shared_memory=shmat(shmid,(void *)0,0);  
  82.     if(shared_memory==(void *)-1)  
  83.     {  
  84.         fprintf(stderr,"shmat failed\n");  
  85.         exit(EXIT_FAILURE);  
  86.     }  
  87.     printf("Memory attached at %X\n",(int)shared_memory);  
  88.   
  89.     /*让结构体指针指向这块共享内存*/  
  90.     shared_stuff=(struct shared_use_st *)shared_memory;  
  91.   
  92.     /*循环的向共享内存中写数据,直到写入的为“end”为止*/  
  93.     while(running)  
  94.     {  
  95. /******************************************************************************/  
  96.         //获取信号量   
  97.         if(semop(semid, &p_op_buf, 1)<0)  
  98.         {  
  99.         printf("semop failed\n");  
  100.         exit(EXIT_FAILURE);  
  101.         }  
  102.         printf("shm2 get the semaphore\n");  
  103. /******************************************************************************/  
  104.           
  105.         printf("Ener some text:");  
  106.         fgets(buffer,BUFSIZ,stdin);  
  107.         strncpy(shared_stuff->some_text,buffer,TEXT_SZ);  
  108.         shared_stuff->written_by_you=1;  
  109.         if(strncmp(buffer,"end",3)==0)  
  110.         {  
  111.             running=0;  //结束循环   
  112.         }  
  113.   
  114. /*****************************************************************************/  
  115.         //释放信号量   
  116.         v_op_buf.sem_num = 0;  
  117.         v_op_buf.sem_op = 1;  
  118.         v_op_buf.sem_flg = 0;  
  119.         if(semop(semid, &v_op_buf, 1)<0)  
  120.         {  
  121.             printf("semop release semaphore failed\n");  
  122.             exit(EXIT_FAILURE);  
  123.         }  
  124.         printf("semop release semaphore ok\n");  
  125. /*****************************************************************************/  
  126.     }  
  127.   
  128.     /*删除共享内存*/  
  129.     if(shmdt(shared_memory)==-1)  
  130.     {  
  131.         fprintf(stderr,"shmdt failed\n");  
  132.         exit(EXIT_FAILURE);  
  133.     }  
  134.     exit(EXIT_SUCCESS);  
  135. }  

客户端:

  1. #include <unistd.h>   
  2. #include <stdlib.h>   
  3. #include <stdio.h>   
  4. #include <string.h>   
  5. #include <sys/types.h>   
  6. #include <sys/ipc.h>   
  7. #include <sys/shm.h>   
  8. #include "shm_com.h"   
  9.   
  10. #include <sys/sem.h>   
  11.   
  12. int main(void)  
  13. {  
  14.     int running=1;  
  15.     void *shared_memory=(void *)0;  
  16.     struct shared_use_st *shared_stuff;  
  17.     int shmid;  
  18. /***************************************************************/     
  19.     int pid,semid;  
  20.     key_t semkey;  
  21.     if((semkey=ftok("/home", 1))<0)  
  22.     {  
  23.         printf("ftok failed\n");  
  24.         exit(EXIT_FAILURE);  
  25.     }  
  26.     printf("ftok ok, semkey=%d\n", semkey);  
  27.       
  28.     if((semid=semget(semkey, 0, 0))<0)  
  29.     {  
  30.         printf("semget failed\n");  
  31.         exit(EXIT_FAILURE);  
  32.     }  
  33.     printf("semget ok, semid = %d\n", semid);  
  34.       
  35.     if((semctl(semid, 0, SETVAL, 1))<0)  
  36.     {  
  37.         printf("semctl set sermval failed\n");  
  38.         exit(EXIT_FAILURE);  
  39.     }  
  40.     printf("semctl set semval ok\n");  
  41.       
  42.     struct sembuf p_op_buf, v_op_buf;  
  43.     p_op_buf.sem_num=0;  
  44.     p_op_buf.sem_op = -1;  
  45.     p_op_buf.sem_flg = 0;  
  46.       
  47. /******************************************************************/  
  48.     /*创建共享内存*/  
  49.     shmid=shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);  
  50.     if(shmid==-1)  
  51.     {  
  52.         fprintf(stderr,"shmget failed\n");  
  53.         exit(EXIT_FAILURE);  
  54.     }  
  55.   
  56.     /*映射共享内存*/  
  57.     shared_memory=shmat(shmid,(void *)0,0);  
  58.     if(shared_memory==(void *)-1)  
  59.     {  
  60.         fprintf(stderr,"shmat failed\n");  
  61.         exit(EXIT_FAILURE);  
  62.     }  
  63.     printf("Memory attached at %X\n",(int)shared_memory);  
  64.   
  65.     /*让结构体指针指向这块共享内存*/  
  66.     shared_stuff=(struct shared_use_st *)shared_memory;  
  67.   
  68.     /*控制读写顺序*/  
  69.     //shared_stuff->written_by_you=0;   
  70.   
  71.     /*循环的从共享内存中读数据,直到读到“end”为止*/  
  72.     while(running)  
  73.     {  
  74. /* 
  75.        if(shared_stuff->written_by_you) 
  76.        { 
  77.          printf("You wrote:%s",shared_stuff->some_text); 
  78.            sleep(1);  //读进程睡一秒,同时会导致写进程睡一秒,这样做到读了之后再写 
  79.            shared_stuff->written_by_you=0; 
  80.            if(strncmp(shared_stuff->some_text,"end",3)==0) 
  81.            { 
  82.                running=0; //结束循环 
  83.            } 
  84.        } 
  85. */  
  86. /******************************************************************************/  
  87.         //获取信号量   
  88.         if(semop(semid, &p_op_buf, 1)<0)  
  89.         {  
  90.         printf("semop failed\n");  
  91.         exit(EXIT_FAILURE);  
  92.         }  
  93.         printf("shm1 get the semaphore\n");  
  94. /*******************************************************************************/  
  95.   
  96.         printf("You wrote:%s",shared_stuff->some_text);  
  97.         sleep(1);  //读进程睡一秒,同时会导致写进程睡一秒,这样做到读了之后再写   
  98.   
  99.         if(strncmp(shared_stuff->some_text,"end",3)==0)  
  100.         {  
  101.            running=0; //结束循环   
  102.         }  
  103.           
  104. /****************************************************************************/        
  105.         //释放信号量   
  106.         v_op_buf.sem_num = 0;  
  107.         v_op_buf.sem_op = 1;  
  108.         v_op_buf.sem_flg = 0;  
  109.         if(semop(semid, &v_op_buf, 1)<0)  
  110.         {  
  111.             printf("semop release semaphore failed\n");  
  112.             exit(EXIT_FAILURE);  
  113.         }  
  114.         printf("semop release semaphore ok\n");  
  115. /*****************************************************************************/  
  116.          
  117.     }  
  118. /*******************************************************************************/  
  119.   
  120.     /*删除共享内存*/  
  121.     if(shmdt(shared_memory)==-1)  
  122.     {  
  123.         fprintf(stderr,"shmdt failed\n");  
  124.         exit(EXIT_FAILURE);  
  125.     }  
  126.   exit(EXIT_SUCCESS);  
  127. }  
以后的解决方案是先把那个信号量的程序由一个程序拆分成两个,彻底掌握信号量通信的过程。再来改造共享内存读写顺序。课程还要继续有机会再来解决吧!还一个实现上边 的方法参考这里



原文地址:https://www.cnblogs.com/hehehaha/p/6332962.html