当前位置: 首页 > 知识库问答 >
问题:

具有2个信号量组和共享内存的进程

乐健
2023-03-14
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <semaphore.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/wait.h>

int sum =0;

int compute(int data){
    sum += data;
    return sum;
}

int main(){
    int i;
    int shm_id;
    int data;
    pid_t pid;
    key_t shm_key;
    sem_t *sem;
    // unsigned int sem_value =2;
    shm_key = ftok("/dev/null", 65);
    shm_id = shmget(shm_id, sizeof(int), 0644 | IPC_CREAT);
    if (shm_id < 0){
        perror("shmgget");
        exit(EXIT_FAILURE);
    }
    // data = shmat(shm_id, NULL, 0);
    sem = sem_open("semaphore", O_CREAT | O_EXCL, 0644, 2);

    for (i = 0; i < 2; i++){
        pid = fork();
        if (pid < 0)
        {
            perror("fork");
            sem_unlink("semaphore");
            sem_close(sem);
            exit(EXIT_FAILURE);
        }
        else if (pid == 0)
        {
            break;
        }
    }
    if (pid == 0)
    {
        puts("Enter the data:");
        scanf("%d", &data);
        //child process
        sem_wait(sem);
        printf("Child - %d is in critical section\n", i);
        sleep(1);

        puts("Enter the data:");
        scanf("%d", &data);
        // *shrd_value += data;
        printf("Child - %d: new value of data = %d\n", i, data);
        printf("Child - %d: sum of whole data by far = %d\n", i, compute(data));
        sem_post(sem);
        exit(EXIT_SUCCESS);
    }
    else if (pid > 0)
    {
        //parent process
        while (pid = waitpid(-1, NULL, 0))
        {
            if (errno == ECHILD)
            {
                break;
            }
        }
        puts("All children exited");
        shmdt(&data);
        shmctl(shm_id, IPC_RMID, 0);
        sem_unlink("semaphore");
        sem_close(sem);         
        exit(0);
    }
}
Enter the data:
Enter the data:
2
Child - 0 is in critical section
1Enter the data:

Child - 1 is in critical section
Enter the data:
3
Child - 0: new value of data = 3
Child - 0: sum of whole data by far = 3
2
Child - 1: new value of data = 2
Child - 1: sum of whole data by far = 2
All children exited

共有1个答案

左华灿
2023-03-14

我还修改了它们写入共享内存的方式:它们直接在代码中缺少的shmat调用给出的地址处写入。我修复了一些bug,简化了代码(删除了添加数组的详细日志记录,特别是在进入critial部分之前和之后):

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <semaphore.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/wait.h>

int main(){
    int i;
    int shm_id;
    pid_t pid;
    int *addr; 
    int data;
    pid_t current_pid;
    key_t shm_key;
    sem_t *sem;

    shm_key = ftok("/dev/null", 65);
    shm_id = shmget(shm_key, sizeof(int), 0644 | IPC_CREAT);
    if (shm_id < 0){
        perror("shmget");
        exit(EXIT_FAILURE);
    }

    sem_unlink("semaphore");
    sem = sem_open("semaphore", O_CREAT, 0644, 1);
    if (sem == SEM_FAILED) {
        perror("sem_open");
        exit(EXIT_FAILURE);
    } 

    addr = (int *) shmat(shm_id, (void *) 0, 0);   
    if (addr == (void *) -1) {
        perror("shmat");
        exit(EXIT_FAILURE);
    }
    *addr = 0;

    for (i = 0; i < 2; i++){
        pid = fork();
        if (pid < 0)
        {
            perror("fork");
            sem_close(sem);
            sem_unlink("semaphore");
            exit(EXIT_FAILURE);
        }
    }


    if (pid == 0)
    {
    current_pid = getpid();
        printf("Child %d: waiting for critical section \n", current_pid);
        sem_wait(sem);
        printf("Child %d: enters in critical section \n", current_pid);
        printf("child %d: Enter the data:\n", current_pid);
        scanf("%d", &data);
        printf("Child %d: new value of data = %d\n", current_pid, data);
        printf("Child %d: sum of whole data so far = %d\n", current_pid, *addr += data);
        sem_post(sem);
    printf("Child %d exits from critical section\n", current_pid);
        exit(EXIT_SUCCESS);
    }
    else if (pid > 0)
    {
        //parent process
        while (pid = waitpid(-1, NULL, 0))
        {
            if (errno == ECHILD)
            {
                break;
            }
        }
        puts("All children exited");
        shmdt(addr);
        shmctl(shm_id, IPC_RMID, 0);
        sem_close(sem);         
        sem_unlink("semaphore");
        exit(0);
    }

    exit(0);
}

请注意,信号量初始值必须为1,才能有2个进程的真正临界区段。

我还删除了睡眠调用,我们可以看到其中一个过程正在等待:

Child 22514: waiting for critical section 
Child 22514: enters in critical section 
child 22514: Enter the data:
Child 22515: waiting for critical section 
333
Child 22514: new value of data = 333
Child 22514: sum of whole data so far = 333
Child 22514 exits from critical section
Child 22515: enters in critical section 
child 22515: Enter the data:
666
Child 22515: new value of data = 666
Child 22515: sum of whole data so far = 999
Child 22515 exits from critical section
All children exited
All children exited
 类似资料:
  • 我想创建一个共享内存和信号量的C程序。应该有两个子进程。两个孩子都有一个不同的int数。然后有一个目标号码,应该写在共享内存中。现在两个孩子都应该从进球数中减去他们的数字,直到进球数低于或等于0。我不希望出现比赛条件。这就是为什么我尝试使用信号量。但对我没用。下面是我的代码:

  • 我尝试编写一个共享内存和信号量程序,该程序一直运行到按下Ctrl+C,即接收到: 当按下Ctrl+C时,被设置为,它会跳出循环并退出。在没有共享内存和信号量的情况下,这可以很好地工作,但是在这里,我从来没有在上获得字符串,只捕获并且它继续运行。 为什么?

  • 我需要编写一个程序,它正在创建N个数量的子进程,每一个进程都将一个添加到共享内存变量中。我的想法是使用信号量和共享内存,但进程之间并没有相互等待,共享内存变量也没有像我希望的那样工作。 MyDefs.H Main.C 奴隶Proc.c

  • 它编译得很好,但是当我试图运行它时,当它到达部分时,我得到了一个分段错误。我在其他地方读到过,不应该创建指向信号量的指针,但是当我没有创建并尝试时,我遇到了一个关于需要lvalue的错误。任何帮助都将不胜感激。

  • 我在Linux上使用C。我需要构建使用共享内存和信号量进行通信的两个程序。 其中一个程序必须充当服务器(一次只能充当一个),另一个程序必须充当客户机(一次任意数量)。通信应遵循以下模式: 我知道如何在两个进程之间使用共享内存和信号量,但我不知道如何在数量不明的进程之间进行通信时使用它们。我考虑为每个客户机使用共享内存块,但我必须交换密钥并通知服务器新的客户机。所以这并不能解决问题。