找回密码
 立即注册
首页 业界区 安全 系统编程练习题----使用消息队列实现两个进程之间的通信 ...

系统编程练习题----使用消息队列实现两个进程之间的通信

焦听云 3 天前
目录

  • 题目
  • 思路
  • 代码展示

    • 进程A
    • 进程B

  • 结果展示

题目

要求进程A创建一条消息队列之后向进程B发送SIGUSR1信号,进程B收到该信号之后打开消息队列并写入一段信息作为消息写入到消息队列中,要求进程B在写入消息之后,发SIGUSR2信号给进程A,进程A收到该信号则从消息队列中读取消息并输出消息正文的内容。
思路


  • 通过进程A创建的消息队列,实现进程A与进程B之间的PID交换
  • 通过kill指令完成进程A与进程B之间的信号交互,并通过状态机实现步骤的进行
  • 进程A收到进程B的信号后,从消息队列中读出消息,并完成显示
代码展示

进程A
  1. /*******************************************************************
  2. *
  3. *        file name:        process_A.c
  4. *        author         :  790557054@qq.com
  5. *        date         :  2024/05/27
  6. *        function :  该案例是掌握进程通信方式,主要是学习信号和消息队列的使用
  7. *         note         :  None
  8. *   version  :
  9. *
  10. *        CopyRight (c)  2023-2024   790557054@qq.com   All Right Reseverd
  11. *
  12. * *****************************************************************/
  13. /****************************头文件**************************************/
  14. #include <stdio.h>
  15. #include <sys/types.h>
  16. #include <sys/ipc.h>
  17. #include <errno.h>
  18. #include <string.h>
  19. #include <signal.h>
  20. #include <sys/msg.h>
  21. #include <stdlib.h>
  22. #include <unistd.h>
  23. /****************************结构体**************************************/
  24. struct msgbuf
  25. {
  26.         long mtype;       /* message type, must be > 0 */
  27.         int mtext;    /* message data */
  28. };
  29. /****************************全局变量**************************************/
  30. volatile int  flag;  //作为状态机条件
  31. /********************************************************************
  32. *
  33. *        name         :        msg_get
  34. *        function :  改函数用于获取进程B发送的信号
  35. *        pqram :  
  36. *                                @signum  : 捕捉到的信号类型
  37. *                               
  38. *        retval         :  none
  39. *        author         :  790557054@qq.com
  40. *        date         :  2024/05/27
  41. *         note         :  none
  42. *   version  :
  43. *        
  44. * *****************************************************************/
  45. void msg_get(int signum)
  46. {
  47.         if(signum == SIGUSR1)
  48.         {
  49.                 //改变标志量,从消息队列中读取进程B的pid
  50.                 flag = 1;
  51.         }
  52.         else if(signum == SIGUSR2)
  53.         {
  54.                 //改变标志量,从消息队列中读取进程B发送的消息
  55.                 flag = 0;
  56.         }
  57. }
  58. int main(int argc, char const *argv[])
  59. {
  60.         //捕捉进程B发送的信号,再从消息队列中获取进程B的pid
  61.         signal(SIGUSR1, msg_get);
  62.         //捕捉进程B发送的信号,再从消息队列中获取进程B发送的消息
  63.         signal(SIGUSR2, msg_get);
  64.         /****创建一条消息队列****/
  65.         //1) 获取消息队列唯一键值(key)
  66.         key_t key = ftok(".", 0xffffff01);
  67.         //2) 定义一个变量用于存储消息队列id,创建一条消息队列
  68.         int msg_id = msgget(key, IPC_CREAT | 0644);
  69.         if(msg_id == -1)
  70.         {
  71.                 fprintf(stderr, "msgget error , errno: %d, %s\n", errno, strerror(errno));
  72.                 exit(-1);
  73.         }
  74.         /****发送SIGUSR1信号给进程B****/
  75.         // 通过消息队列完成A,B进程的pid交换
  76.         //1. 将进程A的pid写入消息队列中
  77.         struct msgbuf msg_pid;
  78.         msg_pid.mtype = 1;
  79.         msg_pid.mtext = getpid();
  80.         msgsnd(msg_id, &msg_pid, 4, 0);
  81.         //2. 捕捉进程B发送的SIGUSR1信号
  82.         while(flag == 0);
  83.         // 3. 从消息队列中读取进程B的pid
  84.         struct msgbuf msg_pid_B;
  85.         msgrcv(msg_id, &msg_pid_B, 4, 1, IPC_NOWAIT);
  86.         //4. 发送SIGUSR1信号给进程b
  87.         kill(msg_pid_B.mtext, SIGUSR1);
  88.         /****接收到进程B的信号后,从消息队列中读出消息并输出****/
  89.         while(flag);
  90.         struct msgbuf msg_num;
  91.         msgrcv(msg_id, &msg_num, 4, 2, IPC_NOWAIT);
  92.         printf("The information received from process B is %d\n", msg_num.mtext);
  93.         return 0;
  94. }
复制代码
进程B
  1. /*******************************************************************
  2. *
  3. *        file name:        process_B.c
  4. *        author         :  790557054@qq.com
  5. *        date         :  2024/05/27
  6. *        function :  该案例是掌握进程通信方式,主要是学习信号和消息队列的使用
  7. *         note         :  None
  8. *   version  :
  9. *
  10. *        CopyRight (c)  2023-2024   790557054@qq.com   All Right Reseverd
  11. *
  12. * *****************************************************************/
  13. /****************************头文件**************************************/
  14. #include <stdio.h>
  15. #include <sys/types.h>
  16. #include <sys/ipc.h>
  17. #include <errno.h>
  18. #include <string.h>
  19. #include <signal.h>
  20. #include <sys/msg.h>
  21. #include <stdlib.h>
  22. #include <unistd.h>
  23. /****************************结构体**************************************/
  24. struct msgbuf
  25. {
  26.         long mtype;       /* message type, must be > 0 */
  27.         int mtext;    /* message data */
  28. };
  29. /****************************全局变量**************************************/
  30. volatile int  flag = 1;  //作为状态机条件
  31. /********************************************************************
  32. *
  33. *        name         :        msg_get
  34. *        function :  改函数用于获取进程A发送的信号
  35. *        pqram :  
  36. *                                @signum  : 捕捉到的信号类型
  37. *                               
  38. *        retval         :  none
  39. *        author         :  790557054@qq.com
  40. *        date         :  2024/05/27
  41. *         note         :  none
  42. *   version  :
  43. *        
  44. * *****************************************************************/
  45. void msg_get(int signum)
  46. {
  47.         if(signum == SIGUSR1)
  48.         {
  49.                 //改变标志量,从消息队列中读取进程A的pid
  50.                 flag = 0;
  51.         }
  52. }
  53. int main(int argc, char const *argv[])
  54. {
  55.         //捕捉进程A发送的信号,再从消息队列中获取进程B的pid
  56.         signal(SIGUSR1, msg_get);
  57.         /****打开一条消息队列****/
  58.         //1) 获取消息队列唯一键值(key)
  59.         key_t key = ftok(".", 0xffffff01);
  60.         //2) 定义一个变量用于存储消息队列id,创建一条消息队列
  61.         int msg_id = msgget(key, IPC_CREAT | 0644);
  62.         if(msg_id == -1)
  63.         {
  64.                 fprintf(stderr, "msgget error , errno: %d, %s\n", errno, strerror(errno));
  65.                 exit(-1);
  66.         }
  67.         struct msgbuf msg_pid_a;
  68.         /****从消息队列中读取进程A的pid,并将进程B的pid写入消息队列中***/
  69.         msgrcv(msg_id, &msg_pid_a, 4, 1, IPC_NOWAIT);
  70.         //将进程B的pid写入消息队列
  71.         struct msgbuf msg_pid_b;
  72.         msg_pid_b.mtype = 1;
  73.         msg_pid_b.mtext = getpid();
  74.         msgsnd(msg_id, &msg_pid_b, 4, 0);
  75.         /****发送SIGUSR1信号给进程A****/
  76.         kill(msg_pid_a.mtext, SIGUSR1);
  77.         /****等待接收进程A的SIGUSR1信号****/
  78.         while(flag == 1);
  79.         /****接收到进程A的信号后,将数据写入消息队列中***/
  80.         struct msgbuf msg_num;
  81.         msg_num.mtype = 2;
  82.         msg_num.mtext = 66666;
  83.         msgsnd(msg_id, &msg_num, 4, 0);
  84.         /****发送SIGUSR2信号给进程A****/
  85.         kill(msg_pid_a.mtext, SIGUSR2);
  86.         return 0;
  87. }
复制代码
结果展示

1.png


来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册