• 利用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
  • 相关阅读:
    JSTLView快速国际化(SpringMVC)
    SprngMVC源码学习
    请求数据传入(SpringMVC)
    @ModelAttribute注解(SpringMVC)
    SpringMVC-RESTRUL___CRUD知识点总结
    SpringMVC视图解析器概述
    Spring
    英文单词
    关于陌生的依赖模块,如withStyles、react-apollo等
    React项目中那些奇怪的写法
  • 原文地址:https://www.cnblogs.com/pengdonglin137/p/2952418.html
Copyright © 2020-2023  润新知