鱼C论坛

 找回密码
 立即注册
查看: 2746|回复: 2

进程间的通信

[复制链接]
发表于 2017-7-6 12:00:14 | 显示全部楼层 |阅读模式
8鱼币
当程序运行时,父进程 fork 出 4 个子进程。父进程负责产生消息(每 1s 产生一个消息), 4 个子进程负责处理消息。父子进程之间通过消息队列来传递消息。
父进程需要维护一个本地数据库(格式与共享数据库相同),当生成一个消息时,父进程要同步更新本地数据库。子进程在处理消息时,根据消息的内容来对共享数据库进行更新(比如,当一个子进程收到一个[index=2, op=increase]的消息时,需要将共享数据库中 index 为 2 的条目的 count 值递增 1 ),并延迟 500ms 。
父进程需要处理 SIGTERM 信号。父进程接收到 SIGTERM 信号意味着要求结束该程序。在结束程序之前,父进程要结束所有子进程、显示并对比本地数据库和共享数据库中的信息(两者应该相同)。

捕获.PNG
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-7-6 20:47:00 | 显示全部楼层
有点意思,好好写
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-7-7 11:47:26 | 显示全部楼层
本帖最后由 json 于 2017-7-7 11:49 编辑

看了一下题意,不是特别理解(估计是我个人问题,哈哈)。写了一个demo,还有许多问题,暂时先抛砖引玉啦~
  1. #include <unistd.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <sys/types.h>
  5. #include <sys/msg.h>
  6. #include <sys/ipc.h>
  7. #include <sys/shm.h>
  8. #include <signal.h>
  9. #include <string.h>

  10. #define OPT_INCR 0
  11. #define OPT_INCRBY 1
  12. #define OPT_DECR 2
  13. #define OPT_DECRBY 3

  14. #define DB_SIZE 10
  15. #define CHILD_COUNT 4

  16. int msgid = 1;
  17. int main_running = 1;
  18. int sub_running = 1;
  19. int pids[CHILD_COUNT];
  20. struct msg_t {
  21.    int opt;
  22.    int index;
  23.    int data;
  24. };

  25. void opt_handler(int * db, struct msg_t * msg) {
  26.    switch (msg->opt) {
  27.    case OPT_INCR:
  28.       db[msg->index] ++;
  29.       break;
  30.    case OPT_INCRBY:
  31.       db[msg->index] += msg->data;
  32.       break;
  33.    case OPT_DECR:
  34.       db[msg->index] --;
  35.       break;
  36.    case OPT_DECRBY:
  37.       db[msg->index] -= msg->data;
  38.       break;
  39.    deafult:
  40.       printf("Not support opt: %d\n", msg->opt);   
  41.    }
  42. }


  43. void child_process(int * shm_db, int msgid) {
  44.    struct msg_t msg;
  45.    struct msqid_ds msg_info;
  46.    while (1) {
  47.       sleep(0.5);
  48.       msgctl(msgid, IPC_STAT, &msg_info);
  49.       if (msg_info.msg_qnum <= 0) {
  50.          //sleep(CHILD_COUNT);
  51.          if (!sub_running) break;
  52.          continue;
  53.       }
  54.       if (msgrcv(msgid, (struct msg_t *)&msg, sizeof(&msg), 0, 0) == -1) {
  55.          fprintf(stderr, "subpid[%d]: msgcrv failed\n", getpid());
  56.          continue;
  57.       }
  58.       printf("GET[%d]: %d, %d, %d\n", getpid(), msg.opt, msg.index, msg.data);
  59.       opt_handler(shm_db, &msg);
  60.    }
  61.    exit(EXIT_SUCCESS);
  62. }

  63. void show_db(int * db, int * shm_db) {
  64.    int i;
  65.    printf("index\tlocal val\tshm val\n");
  66.    for (i = 0; i < DB_SIZE; i++) {
  67.       printf("%d\t%d\t\t%d\n", i, db[i], shm_db[i]);
  68.    }
  69. }

  70. void sub_usr1_handler() {
  71.    sub_running = 0;
  72. }

  73. void term_handler() {
  74.    printf("I got SIGTERM...\n");
  75.    main_running = 0;
  76.    int i;
  77.    for (i = 0; i < CHILD_COUNT; i++) {
  78.       kill(pids[i], SIGUSR1);
  79.    }
  80. }


  81. int main() {
  82.    int db[DB_SIZE], *shm_db, i, status=0, wpid;
  83.    key_t mapKey = (key_t)1234, msgKey = (key_t)4321;
  84.    struct msg_t msg;
  85.    
  86.    char *pidfile = "tmp.pid";
  87.    int pid = getpid();
  88.    char pid_s[8];
  89.    sprintf(pid_s, "%d", pid);
  90.    FILE * fp = fopen(pidfile, "w");
  91.    if (fp == NULL) {
  92.       fprintf(stderr, "open %s file failed.\n", pidfile);
  93.       exit(EXIT_FAILURE);
  94.    }
  95.    fwrite(pid_s, sizeof(pid_s), 1, fp);
  96.    fclose(fp);

  97.    srand((unsigned)time(NULL));

  98.    msgid = msgget(msgKey, 0666 | IPC_CREAT);
  99.    if (msgid == -1) {
  100.       fprintf(stderr, "msgget error.\n");
  101.       exit(EXIT_FAILURE);
  102.    }

  103.    int shmid = shmget(mapKey, sizeof(db), IPC_CREAT);
  104.    if (shmid == -1) {
  105.       fprintf(stderr, "shmget error.\n");
  106.       exit(EXIT_FAILURE);
  107.    }
  108.    
  109.    shm_db = (int *)shmat(shmid, NULL, 0);
  110.    
  111.    memset(db, 0, sizeof(db));
  112.    memset(shm_db, 0, sizeof(db));

  113.    struct sigaction subsig;
  114.    subsig.sa_handler = sub_usr1_handler;
  115.    sigemptyset(&subsig.sa_mask);
  116.    subsig.sa_flags = SA_RESETHAND;
  117.    sigaction(SIGUSR1, &subsig, 0);

  118.    for (i = 0; i < CHILD_COUNT; i++) {
  119.       if ((pids[i] =fork()) == 0) {
  120.          child_process(shm_db, msgid);
  121.       }
  122.    }

  123.    struct sigaction sig;
  124.    sig.sa_handler = term_handler;
  125.    sigemptyset(&sig.sa_mask);
  126.    sig.sa_flags = SA_RESETHAND;
  127.    sigaction(SIGTERM, &sig, 0);

  128.    show_db(db, shm_db);

  129.    while (main_running) {
  130.       msg.opt = rand()%4;
  131.       msg.index = rand()%8 + 1;
  132.       msg.data = rand()%10 + 1;
  133.       printf("POST[%d]: %d, %d, %d\n", getpid(), msg.opt, msg.index, msg.data);
  134.       if (msgsnd(msgid, &msg, sizeof(&msg), 0) == -1) {
  135.          fprintf(stderr, "msgsnd failed\n");
  136.          continue;
  137.       }
  138.       opt_handler(db, &msg);
  139.       sleep(1);
  140.    }

  141.    while( (wpid = wait(&status)) > 0) {
  142.       printf("subproc[%d] exit.\n", wpid);
  143.    }
  144.    
  145.    show_db(db, shm_db);

  146.    if (msgctl(msgid, IPC_RMID, 0) == -1) {
  147.       fprintf(stderr, "msgctl error.\n");
  148.       exit(EXIT_FAILURE);
  149.    }

  150.    if (shmdt(shm_db) == -1) {
  151.       fprintf(stderr, "shm detach error\n");
  152.       exit(EXIT_FAILURE);
  153.    }

  154.    if (shmctl(shmid, IPC_RMID, 0) == -1) {
  155.       fprintf(stderr, "shm remove failed.\n");
  156.       exit(EXIT_FAILURE);
  157.    }

  158.    exit(EXIT_SUCCESS);
  159. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-19 21:19

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表