简体   繁体   English

具有 2 个信号量组并共享 memory 的进程

[英]Processes with group of 2 semaphores and shared memory

I write a program containing two processes: the first one contains a group of two semaphores and creates the child process that reads all data in the shared memory segment and prints them.我编写了一个包含两个进程的程序:一个包含一组两个信号量并创建子进程,该子进程读取共享 memory 段中的所有数据并打印它们。

In the second one, the child process computes the data using a compute function that returns 0 when all data are computed.第二个中,子进程使用计算 function 计算数据,当计算所有数据时返回 0。 It transmits them to the parent through the shared memory segment.它通过共享的 memory 段将它们传输给父级。

To write data:写入数据:

  • On the 1st semaphore the child makes P and the parent make V.在第一个信号量中,孩子发出 P,父母发出 V。

  • On the 2nd semaphore the child makes V and the parent make P.在第二个信号量上,孩子做 V,父母做 P。

But as I'm new in this topic and still getting hardness to understand, it seems like I'm doing something wrong because it's not working as it has to be.但是由于我是这个主题的新手并且仍然难以理解,所以我似乎做错了什么,因为它没有按应有的方式工作。

Here is my code:这是我的代码:

#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);
    }
}

Output: Output:

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

I have also modified the way they write to shared memory: they write directly at the address given by shmat call that is missing in your code.我还修改了他们写入共享 memory 的方式:他们直接写入代码中缺少的 shmat 调用给出的地址。 I have fixed some bugs and simplifed the code (removed the array - added detailed logging especially before and after entering the critial section):我已经修复了一些错误并简化了代码(删除了数组 - 特别是在进入关键部分之前和之后添加了详细的日志记录):

#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);
}

Note that semaphore initial value must be 1 to have a true critical section for 2 processes.请注意,信号量初始值必须为 1 才能拥有 2 个进程的真正临界区。

I have also removed the sleep calls and we can see that one of the process is waiting:我还删除了睡眠调用,我们可以看到其中一个进程正在等待:

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

Here's the code with producer and consumer process这是生产者和消费者进程的代码

#include <stdio.h> 
#include <stdlib.h>
#include <fcntl.h>         // O_CREAT, O_EXEC
#include <errno.h>         // errno, ECHILD     
#include <unistd.h>
#include <sys/shm.h>       // shmat(), IPC_RMID
#include <sys/wait.h> 
#include <semaphore.h>     // sem_open(), sem_destroy(), sem_wait()...
#include <sys/types.h>     // key_t, sem_t, pid_t
#include <pthread.h>

#define BUFF 10

typedef struct data{
    int buff[BUFF];
    int size;
    int index;
}DATA;

int main(int argc, char const *argv[])
{
    sem_t *full, *empty, *access;
    key_t shm_key;
    int shm_id;
    full = sem_open ("fullname", O_CREAT , 0644, 15); 
    empty = sem_open ("empty", O_CREAT , 0644, 0);
    access = sem_open ("access", O_CREAT , 0644, 1);

    if (argc!=2)
    {
        exit(1);
    }

    int value=atoi(argv[1]);

    //initialize a shared variable in shared memory
    shm_key = ftok("/dev/null", 60);
    shm_id = shmget(shm_key, sizeof(DATA), 0);
    // shared memory error check
    if (shm_id < 0){
        shm_id = shmget(shm_key, sizeof(DATA), 0644 | IPC_CREAT);
        DATA *data = (DATA*) shmat (shm_id, NULL, 0);
        data->size=0;
        data->index=0; //index 
    }
    printf("Shared memory id: %d\n",shm_id );


    printf("Checking buffer...,\n");
    //If in the buffer have free space then will wait for consumer to consume the data\n"
    sem_wait(empty);

    printf("\nLocking buffer to produce data\n");
    sem_wait(access);


    //initialize a shared variable in shared memory
    shm_key = ftok("/dev/null", 60);
    shm_id = shmget(shm_id, sizeof(DATA), 0644 | IPC_CREAT);
    // shared memory error check
    if (shm_id < 0){
        perror("semaphore");
        exit(EXIT_FAILURE);
    }

    //Shared variable  
    DATA *data = (DATA*) shmat (shm_id, NULL, 0);
    int index=(data->size + data->index) % 15;

    data->buff[index]=value;
    data->size++;
    printf("%d is located in %d on the buffer\n",value,index );



    //consusming

    // attach data to shared memory

    index=data->index;
    value=data->buff[index];

    printf("%d now consumed\n",value );
    data->size--;
    data->index++;



    sem_post(access);
    sem_post(full);



    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM