我在一个主进程和他的孩子们之间用C语言共享记忆,但我无法同步他们的动作

我在一个主进程和他的孩子们之间用C语言共享记忆,但我无法同步他们的动作,c,signals,semaphore,C,Signals,Semaphore,我有一个程序可以做到这一点: 主程序创建了一个共享内存块(与他未来的孩子共享),大小相当于一个名为ClientInfo的结构,其中包含2个整数和一个字符串。然后程序要求用户输入存储在变量n 主程序创建n子程序。然后子程序等待来自其父亲的SIGUSR1信号 主程序向他的所有孩子发送一个SIGUSR1信号 每个子节点从终端读取一个字符串,将其写入共享内存,并以一个单位递增两个共享整数。然后他发送一个信号给他的父亲,睡1到10秒,然后结束 每次父亲收到一个信号1,它就会打印出共享内存的内容,然后只有当

我有一个程序可以做到这一点:

  • 主程序创建了一个共享内存块(与他未来的孩子共享),大小相当于一个名为ClientInfo的结构,其中包含2个整数和一个字符串。然后程序要求用户输入存储在变量n
  • 主程序创建n子程序。然后子程序等待来自其父亲的SIGUSR1信号
  • 主程序向他的所有孩子发送一个SIGUSR1信号
  • 每个子节点从终端读取一个字符串,将其写入共享内存,并以一个单位递增两个共享整数。然后他发送一个信号给他的父亲,睡1到10秒,然后结束
  • 每次父亲收到一个信号1,它就会打印出共享内存的内容,然后只有当他的所有孩子都结束时才会结束
  • “陷阱”是这是大学作业,他们告诉我们,父亲必须能够为每个孩子打印共享记忆的内容一次,因此总共打印n次。此外,我们不能使用sigwait()或全局变量(除非全局变量是唯一的方法)

    而且每次我运行程序时,它都会在请求n

    我知道一定有一些比赛条件,但我真的很糟糕,我不知道怎么了

    先谢谢你

    代码如下:

    
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #定义SHM_名称“/SHM_示例”
    #定义SEM1“/示例\u SEM1”
    #定义SEM2“/示例\u SEM2”
    #定义名称\u最大值100
    类型定义结构{
    int上一个客户端的上一个\u id;/!previous\u id)=-1;
    (示例_struct->id)=0;
    对于(i=0;i上一个id)+;
    printf(“名称为:\n的介绍”);
    scanf(“%s”,名称);
    memcpy(示例_struct->name、nombre、sizeof(nombre));
    (示例_struct->id)+;
    kill(getppid(),SIGUSR1);
    sem_post(sem_write);
    睡眠(1+(rand()%10));
    退出(退出成功);
    }
    }
    sigprocmask(SIG_解除阻塞、屏蔽和旧屏蔽);
    kill(0,SIGUSR1);
    sigprocmask(SIG_块、掩码和旧掩码);
    而(1){
    sigsupspend(&oldsmask);
    /*if(等待(空)名称,示例\u结构->id,示例\u结构->上一个\u id);
    fflush(stdout);
    sigpemptyset(&mask);
    sigaddset(&mask,SIGUSR1);
    sigprocmask(SIG_块、掩码和旧掩码);
    sem_wait(sem_read);
    sem_post(sem_write);
    sem_post(sem_read);}
    }
    
    您可以尝试以下方法:

    #include <stdbool.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/mman.h>
    #include <sys/stat.h>        /* For mode constants */
    #include <fcntl.h>           /* For O_* constants */
    #include <unistd.h>
    #include <sys/stat.h>
    #include <sys/wait.h>
    #include <stdatomic.h>
    
    #define SHM_NAME "/shm_example"
    
    #define NAME_MAX 100
    
    
    typedef struct{
        char name[NAME_MAX]; //!< Name of the client.
    } ClientInfo;
    
    
    atomic_bool done = ATOMIC_VAR_INIT(false);
    
    void child_handler(int dummy) {
        (void)dummy;
        done = true;
    }
    
    int main(void) {
    
        int i,n,*pids;
        int fd_shm;
        int error;
        struct sigaction act;
        ClientInfo *example_struct;
    
        printf("Introduzca un numero:\n");
        scanf("%d",&n);
    
        if(!(pids = malloc(n*sizeof(int))))
            exit(EXIT_FAILURE);
    
        sigemptyset(&(act.sa_mask));
        act.sa_flags = 0;
        act.sa_handler = child_handler;
        if (sigaction(SIGUSR1, &act, NULL) < 0) {
            perror("sigaction");
            exit(EXIT_FAILURE);
        }
    
        fd_shm = shm_open(SHM_NAME,O_RDWR | O_CREAT | O_EXCL,S_IRUSR | S_IWUSR);
    
        if(fd_shm == -1) {
            fprintf (stderr, "Error creating the shared memory segment \n");
            return EXIT_FAILURE;
        }
        error = ftruncate(fd_shm, sizeof(ClientInfo));
    
        if(error == -1) {
            fprintf (stderr, "Error resizing the shared memory segment \n");
            shm_unlink(SHM_NAME);
            return EXIT_FAILURE;
        }
    
        /* Map the memory segment */
        example_struct = (ClientInfo *)mmap(NULL, sizeof(*example_struct), PROT_READ | PROT_WRITE, MAP_SHARED, fd_shm, 0);
    
        if(example_struct == MAP_FAILED) {
            fprintf (stderr, "Error mapping the shared memory segment \n");
            shm_unlink(SHM_NAME);
            return EXIT_FAILURE;
        }
    
        for (i = 0; i < n ; i++) {
            pids[i] = fork();
            if (pids[i] < 0) {
                perror("fork");
                exit(EXIT_FAILURE);
            }
            if (pids[i] == 0) {
                /* Child */
                while (!done) {
                    /* Wait for signal */
                    sleep(1);
                }
                printf("child %d wakes up\n", getpid());
                sprintf(example_struct->name, "my pid is %d", getpid());
                kill(getppid(),SIGUSR1);
                sleep(1 + (rand()%10));
                exit(EXIT_SUCCESS);
            }
        }
    
        /* only father here */
        for (i = 0; i < n; i++) {
            done = false;
            kill(pids[i], SIGUSR1);
            printf("Waiting child %d\n", pids[i]);
            while (!done) {
                /* Wait for signal */
                sleep(1);
            }
            printf("Answer from %d: %s\n", pids[i], example_struct->name);
            wait(NULL);
        }
    }
    

    您可以尝试类似的方法:

    #include <stdbool.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/mman.h>
    #include <sys/stat.h>        /* For mode constants */
    #include <fcntl.h>           /* For O_* constants */
    #include <unistd.h>
    #include <sys/stat.h>
    #include <sys/wait.h>
    #include <stdatomic.h>
    
    #define SHM_NAME "/shm_example"
    
    #define NAME_MAX 100
    
    
    typedef struct{
        char name[NAME_MAX]; //!< Name of the client.
    } ClientInfo;
    
    
    atomic_bool done = ATOMIC_VAR_INIT(false);
    
    void child_handler(int dummy) {
        (void)dummy;
        done = true;
    }
    
    int main(void) {
    
        int i,n,*pids;
        int fd_shm;
        int error;
        struct sigaction act;
        ClientInfo *example_struct;
    
        printf("Introduzca un numero:\n");
        scanf("%d",&n);
    
        if(!(pids = malloc(n*sizeof(int))))
            exit(EXIT_FAILURE);
    
        sigemptyset(&(act.sa_mask));
        act.sa_flags = 0;
        act.sa_handler = child_handler;
        if (sigaction(SIGUSR1, &act, NULL) < 0) {
            perror("sigaction");
            exit(EXIT_FAILURE);
        }
    
        fd_shm = shm_open(SHM_NAME,O_RDWR | O_CREAT | O_EXCL,S_IRUSR | S_IWUSR);
    
        if(fd_shm == -1) {
            fprintf (stderr, "Error creating the shared memory segment \n");
            return EXIT_FAILURE;
        }
        error = ftruncate(fd_shm, sizeof(ClientInfo));
    
        if(error == -1) {
            fprintf (stderr, "Error resizing the shared memory segment \n");
            shm_unlink(SHM_NAME);
            return EXIT_FAILURE;
        }
    
        /* Map the memory segment */
        example_struct = (ClientInfo *)mmap(NULL, sizeof(*example_struct), PROT_READ | PROT_WRITE, MAP_SHARED, fd_shm, 0);
    
        if(example_struct == MAP_FAILED) {
            fprintf (stderr, "Error mapping the shared memory segment \n");
            shm_unlink(SHM_NAME);
            return EXIT_FAILURE;
        }
    
        for (i = 0; i < n ; i++) {
            pids[i] = fork();
            if (pids[i] < 0) {
                perror("fork");
                exit(EXIT_FAILURE);
            }
            if (pids[i] == 0) {
                /* Child */
                while (!done) {
                    /* Wait for signal */
                    sleep(1);
                }
                printf("child %d wakes up\n", getpid());
                sprintf(example_struct->name, "my pid is %d", getpid());
                kill(getppid(),SIGUSR1);
                sleep(1 + (rand()%10));
                exit(EXIT_SUCCESS);
            }
        }
    
        /* only father here */
        for (i = 0; i < n; i++) {
            done = false;
            kill(pids[i], SIGUSR1);
            printf("Waiting child %d\n", pids[i]);
            while (!done) {
                /* Wait for signal */
                sleep(1);
            }
            printf("Answer from %d: %s\n", pids[i], example_struct->name);
            wait(NULL);
        }
    }
    

    为什么不使用信号量进行同步?@OznOg我忘了把代码放在我的问题中(我很累),现在你可以看到信号量了为什么你使用信号量而不是信号量来“通信”?@OznOg因为任务是这样说的,它指定孩子必须发送SIGUSR1给父亲。最后为什么你有信号量,那么?为什么不使用信号量进行同步呢?@OznOg我忘了把代码放在我的问题中(我很累),现在你可以看到信号量了为什么你要用信号量而不是信号量来“通信”?@OznOg因为任务是这样说的,它规定孩子必须在最后将SIGUSR1发送给父亲,那么为什么你有信号量呢?