通过信号访问共享内存给子进程

问题描述

我的c程序需要一些帮助。基本上,在我的c程序中,我希望父进程计算a + b,子进程计算3 *(a + b)。但是,我不发送信号后如何访问共享内存。任何帮助表示赞赏。

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

void sigcont(int shmid); 

int main (int argc,char *argv[]){
    int shmid;
    int *result;
    pid_t pid;

    int size_data = 2 * sizeof (int);
    shmid = shmget (IPC_PRIVATE,size_data,0666 | IPC_CREAT);
    
    pid = fork ();
    if (pid == 0) {
        signal(SIGCONT,sigcont); 
        while (1);
    }
    else {
        sleep(1);
        result = (int *) shmat (shmid,NULL,0);
        result[0] = atoi (argv[2]) + atoi (argv[1]);
        printf ("Result in parent process %d: %d.\n",getpid(),result[0]);
        printf ("Send a SIGCONT to process %d.\n\n",pid);
        shmdt (result);
        kill (pid,SIGCONT);
        wait(NULL);
        printf ("\nThis is the End.\n");
    }
  return 0;
}

void sigcont(int shmid){
    printf("Get a SIGCONT.\n");
    printf("Result in child process ID: %d.\n",getpid());
    exit(0);
}

我尝试过的事情:

  1. 一个参数放入void sigcont(int shmid); 正如我从https://www.geeksforgeeks.org/signals-c-set-2/中学到的。 signal()和kill()是否必须成对使用?我得到这样,我试图将一个值传递给它。无法正常工作。

  2. Sigstop()和Sigcont() 我试图避免在子进程中使用signal(),以便可以直接访问shmid。但是我找不到很多Sigstop()和Sigcont()的示例。它也会失败。

即使看起来很简单,也很难获得我想要的结果。有人能帮忙吗?任何帮助表示赞赏。

解决方法

注意:添加了错误检查;调用shmat()并在fork()之前保存到全局,子级继承附加的共享内存; SIGCONT更适合停止进程,已选择SIGUSR1;信号处理程序的arg是信号#;孩子在旋转,为了使开销最小,最好pause()

此版本为示例,并且尝试支持所设想的每个系统。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int *shmloc;


void shandler(int sig)
{
    printf("pid %d,sig %d\n",getpid(),sig);
    printf("mult result: %d\n",*shmloc * 3);
}


int main(int argc,char *argv[])
{
    int a,b,shmid,size_data,sig;
    pid_t pid;

    if (argc < 3) {
        fprintf(stderr,"missing args a b\n");
        return (1);
    }

    // OP: shmget() size arg,some systems may require a minimum,may roundup
    size_data = 2 * sizeof (int);
    shmid = shmget(IPC_PRIVATE,0666 | IPC_CREAT);
    if (shmid == -1) {
        fprintf(stderr,"shmget failed,%s\n",strerror(errno));
        return (1);
    }

    shmloc = shmat(shmid,NULL,0);
    if (shmloc == (void *) -1) {
        fprintf(stderr,"shmat failed,strerror(errno));
        return (1);
    }

    sig = SIGUSR1;
    pid = fork();
    if (pid < 0) {
        fprintf(stderr,"fork failed,strerror(errno));
        return (1);
    }

    // child only
    if (pid == 0) {
        signal(sig,shandler); 
        pause();
        printf("child exit\n");
        _exit(0);
    }

    sleep(1);
    // OP: care about non-digits in cmd-line args?
    a = atoi(argv[1]);
    b = atoi(argv[2]);
    *shmloc = a + b;
    printf("parent pid %d,add (%d,%d) result %d\n",a,*shmloc);
    shmdt(shmloc);
    printf("sending signal %d to child %d\n",sig,pid);
    kill(pid,sig);
    wait(NULL);
    printf("\nThis is the End.\n");

    return (0);
}