利用pause实现进程间同步一例

完成的功能:一个进程负责将键盘输入的内容写到共享内存,另一个进程负责将共享内存中的数据输出到屏幕上。

两个进程通过pause和kill实现同步。首先运行的进程将自己的pid存到共享内存,然后pause,等待另一个进程将从共享内存中读到的pid保存,然后写入自己的pid后,被对方唤醒。

最后,收到quit命令的进程负责删除共享内存。

writeshm.c

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <sys/types.h>
  4 #include <sys/stat.h>
  5 #include <sys/ipc.h>
  6 #include <string.h>
  7 #include <signal.h>
  8 #include <sys/shm.h>
  9 #include <errno.h>
 10 #include <unistd.h>
 11 
 12 #define N 1024
 13 typedef struct 
 14 {
 15     pid_t pid;
 16     char text[N];
 17 }SHM;
 18 
 19 void handler(int signo) {}
 20 
 21 int main()
 22 {
 23     key_t key;
 24     int shmid;
 25     SHM *shmaddr;
 26     struct shmid_ds buf;
 27     pid_t peerpid;
 28 
 29     signal(SIGUSR1, handler);
 30 
 31     if ((key = ftok(".", 97)) == -1)
 32     {
 33         perror("fork");
 34         exit(-1);
 35     }
 36 
 37     if ((shmid = shmget(key, sizeof(SHM), IPC_CREAT | 0666 | IPC_EXCL)) > 0)   //不存在创建,存在报错EEXIS
 38     {
 39         printf("first run\n");
 40         if ((shmaddr = (SHM *)shmat(shmid, NULL, 0)) == (SHM *)-1)//首先运行,得到共享内存映射后的地址
 41         {
 42             perror("shmat");
 43             exit(-1);
 44         }
 45         shmaddr->pid = getpid(); //将直接的pid存入共享内存
 46         pause();  //进入sleep状态,等待被另一个进程发信号唤醒
 47         peerpid = shmaddr->pid; //保存对方的pid
 48     }
 49     else
 50     {
 51         if (errno == EEXIST)   //说明是第二个运行的
 52         {
 53             printf("last run\n");
 54             shmid = shmget(key, sizeof(SHM), 0666);  //得到共享内存的id
 55             if ((shmaddr = (SHM *)shmat(shmid, NULL, 0)) == (SHM *)-1)
 56             {
 57                 perror("shmat");
 58                 exit(-1);
 59             }
 60             peerpid = shmaddr->pid; //将共享内存中的pid保存起来,就是对方的pid
 61             shmaddr->pid = getpid(); //将自己的pid存入共享内存
 62             kill(peerpid, SIGUSR1);  //唤醒对方
 63         }
 64         else
 65         {
 66             perror("shmget");
 67             exit(-1);
 68         }
 69     }
 70     printf("peerpid=%d\n", peerpid);
 71 
 72     while (1)
 73     {
 74         printf(">");
 75         fgets(shmaddr->text, N, stdin);  //将键盘输入的内容存入共享内存
 76         kill(peerpid, SIGUSR1);     //唤醒对方
 77         if (strncmp(shmaddr->text, "quit", 4) == 0)
 78             break;
 79         pause();  //等待被对方唤醒
 80     }
 81 
 82     if (-1 == shmdt(shmaddr))  //解除映射
 83     {
 84         perror("shmdt");
 85         exit(-1);
 86     }
 87 /* 
 88     if (-1 == shmctl(shmid, IPC_STAT, &buf))  //查询共享内存的状态
 89     {
 90         perror("shmctl stat");
 91         exit(-1);
 92     }
 93     if (buf.shm_nattch == 0)  //如果共享内存没有
 94     {
 95         if (-1 == shmctl(shmid, IPC_RMID, NULL))
 96         {
 97             perror("shmctl rm");
 98             exit(-1);
 99         }
100     }
101  */
102     return 0;
103 }
View Code


readshm.c

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <sys/types.h>
  4 #include <sys/stat.h>
  5 #include <sys/ipc.h>
  6 #include <string.h>
  7 #include <signal.h>
  8 #include <sys/shm.h>
  9 #include <errno.h>
 10 #include <unistd.h>
 11 
 12 #define N 1024
 13 typedef struct 
 14 {
 15     pid_t pid;
 16     char text[N];
 17 }SHM;
 18 
 19 void handler(int signo) {}
 20 
 21 int main()
 22 {
 23     key_t key;
 24     int shmid;
 25     SHM *shmaddr;
 26     struct shmid_ds buf;
 27     pid_t peerpid;
 28 
 29     signal(SIGUSR1, handler);
 30 
 31     if ((key = ftok(".", 97)) == -1)
 32     {
 33         perror("fork");
 34         exit(-1);
 35     }
 36 
 37     if ((shmid = shmget(key, sizeof(SHM), IPC_CREAT | 0666 | IPC_EXCL)) > 0)   //不存在创建,存在报错EEXIS
 38     {
 39         printf("first run\n");
 40         if ((shmaddr = (SHM *)shmat(shmid, NULL, 0)) == (SHM *)-1)
 41         {
 42             perror("shmat");
 43             exit(-1);
 44         }
 45         shmaddr->pid = getpid();
 46         pause();
 47         peerpid = shmaddr->pid;
 48     }
 49     else
 50     {
 51         if (errno == EEXIST)
 52         {
 53             printf("last run\n");
 54             shmid = shmget(key, sizeof(SHM), 0666);
 55             if ((shmaddr = (SHM *)shmat(shmid, NULL, 0)) == (SHM *)-1)
 56             {
 57                 perror("shmat");
 58                 exit(-1);
 59             }
 60             peerpid = shmaddr->pid;
 61             shmaddr->pid = getpid();
 62             kill(peerpid, SIGUSR1);
 63         }
 64         else
 65         {
 66             perror("shmget");
 67             exit(-1);
 68         }
 69     }
 70     printf("peerpid=%d\n", peerpid);
 71 
 72     while (1)
 73     {
 74         pause();   //等待对方写入
 75         sleep(1);
 76         printf("%s", shmaddr->text);
 77         if (strncmp(shmaddr->text, "quit", 4) == 0)
 78             break;
 79         kill(peerpid, SIGUSR1);  //唤醒对方
 80     }
 81 
 82     if (-1 == shmdt(shmaddr))  //解除映射
 83     {
 84         perror("shmdt");
 85         exit(-1);
 86     }
 87 
 88     if (-1 == shmctl(shmid, IPC_STAT, &buf))   //查询共享内存的状态
 89     {
 90         perror("shmctl stat");
 91         exit(-1);
 92     }
 93     if (buf.shm_nattch == 0)  //如果共享内存的映射数为0,则删除共享内存
 94     {
 95         if (-1 == shmctl(shmid, IPC_RMID, NULL))
 96         {
 97             perror("shmctl rm");
 98             exit(-1);
 99         }
100     }
101 
102     return 0;
103 }
View Code
原文地址:https://www.cnblogs.com/pengdonglin137/p/2952418.html