具有2组信号灯和共享内存的进程。

问题描述 投票:0回答:1

我写了一个包含两个进程的程序。第一个 一个包含两组semaphores,并创建子进程,读取共享内存段的所有数据并打印出来。

第二 一,子进程使用计算函数计算数据,当所有数据计算完毕后返回0。它通过共享内存段将这些数据传送给父进程。

要写入数据。

  • 在第一旗语上,子进程做P,父进程做V。

  • 在第2个信标上,子代做V,父代做P。

但是由于我是新手,还在硬着头皮去理解,似乎我做错了什么,因为它没有按照必须的方式工作。

下面是我的代码。

#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
c fork posix semaphore shared-memory
1个回答
1
投票

我还修改了它们向共享内存写入的方式:它们直接在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);
}

请注意,semaphore初始值必须为1,才能对2个进程进行真正的critical部分。

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

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

0
投票

以下是有生产者和消费者进程的代码:

#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;
}
© www.soinside.com 2019 - 2024. All rights reserved.