将char数组从父级传递给子级

时间:2016-03-11 08:37:56

标签: c pipe semaphore

这是我第一次在这里发帖。我是OS编程的新手。

所以我在网上找到了这个程序并决定修改它。父级创建一个包含随机字母的char数组。这封信被传递给孩子,孩子将其删除。

我无法收回孩子的来信。我收到的东西,但它们不是正确的字母。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

#define BUFFER_SIZE 10

#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
#else

union semun
{
    int val;
    struct semid_ds *buf;
    unsigned short int *array;
    struct seminfo *__buf;
};
#endif

int main(int argc, char* argv[])
{
    int sem_set_id;
    union semun sem_val;
    int child_pid;
    int i, j = 0, k;
    struct sembuf sem_op;
    int rc;
    struct timespec delay;

    srand(time(NULL));

    sem_set_id = semget(IPC_PRIVATE, 1, 0600);
    if (sem_set_id == -1)
    {
        perror("main: semget");
        exit(1);
    }
    printf("semaphore set created, semaphore set id '%d'.\n", sem_set_id);

    sem_val.val = 0;
    rc = semctl(sem_set_id, 0, SETVAL, sem_val);

    child_pid = fork();

    char letter[BUFFER_SIZE];

    int fd[2];

    switch (child_pid)
    {
        case -1:
            //fail
            perror("fork");
            exit(1);
        case 0: //child
            close(fd[1]);

            for (i = 0; i < BUFFER_SIZE; i++)
            {
                sem_op.sem_num = 0;
                sem_op.sem_op = -1;
                sem_op.sem_flg = 0;
                semop(sem_set_id, &sem_op, 1);

                read(fd[0], &letter[i], sizeof(letter[i]));

                printf("Consumer removes ");
                printf("['%c'] ", letter[i]);
                printf("at index [%d]\n", i);

                printf("\n");
                fflush(stdout);

                close(fd[1]);
            }
            break;
        default: //parent
            close(fd[0]);

            for (i = 0; i < BUFFER_SIZE; i++)
            {
                //usleep(100);

                letter[i] = (char)num(i);
                write(fd[1], &letter[i], sizeof(letter[i]));

                printf("Producer creates ");
                printf("['%c'] ", letter[i]);
                printf("at index [%d]\n", i);

                printf("\n");
                fflush(stdout);

                sem_op.sem_num = 0;
                sem_op.sem_op = 1;
                sem_op.sem_flg = 0;
                semop(sem_set_id, &sem_op, 1);

                if (rand() > 3 *(RAND_MAX/4))
                {
                    delay.tv_sec = 0;
                    delay.tv_nsec = 10;
                    nanosleep(&delay, NULL);
                }
                close(fd[1]);
            }
            break;
    }

    return 0;
}

int num(int i)
{   
    i = rand() % (90 - 65) + 65;

    return i;
}

以下是示例输出:

semaphore set created, semaphore set id '2850903'.
Producer creates ['N'] at index [0]

Producer creates ['M'] at index [1]

Consumer removes ['0'] at index [0]

Consumer removes ['P'] at index [1]

Producer creates ['E'] at index [2]

Producer creates ['I'] at index [3]

Producer creates ['X'] at index [4]

Consumer removes [''] at index [2]

Consumer removes ['�'] at index [3]

Consumer removes ['�'] at index [4]

Producer creates ['Q'] at index [5]

Consumer removes [''] at index [5]

Producer creates ['M'] at index [6]

Consumer removes [''] at index [6]

Producer creates ['F'] at index [7]

Consumer removes [''] at index [7]

Producer creates ['M'] at index [8]

Producer creates ['D'] at index [9]

Consumer removes [''] at index [8]

Consumer removes [''] at index [9]

EDIT1 我使用共享内存。孩子只识别父母在数组上添加的最后一个字母并重复它。

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

#define BUFFER_SIZE 10

#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
#else

union semun
{
        int val;
        struct semid_ds *buf;
        unsigned short int *array;
        struct seminfo *__buf;
};
#endif

int main(int argc, char* argv[])
{
    char letter[BUFFER_SIZE];

    int shmid;

    void *shm = NULL;

    shmid = shmget((key_t)1, sizeof(int), 0666|IPC_CREAT);
    shm = shmat(shmid, 0, 0);

    int *shared = (int*)shm;

    *shared = 0;

    int sem_set_id;
    union semun sem_val;
    int child_pid;
    int i, j = 0, k;
    struct sembuf sem_op;
    int rc;
    struct timespec delay;

    srand(time(NULL));

    sem_set_id = semget(IPC_PRIVATE, 1, 0600);
    if (sem_set_id == -1)
    {
        perror("main: semget");
        exit(1);
    }
    printf("semaphore set created, semaphore set id '%d'.\n", sem_set_id);

    sem_val.val = 0;
    rc = semctl(sem_set_id, 0, SETVAL, sem_val);

    child_pid = fork();

    switch (child_pid)
    {
        case -1:
            //fail
            perror("fork");
            exit(1);
        case 0: //child

            for (i = 0; i < BUFFER_SIZE; i++)
            {
                sem_op.sem_num = 0;
                sem_op.sem_op = -1;
                sem_op.sem_flg = 0;
                semop(sem_set_id, &sem_op, 1);

                printf("Consumer removes ");
                printf("['%c'] ", *shared);
                printf("at index [%d]\n", i);

                printf("\n");
                fflush(stdout);
            }
            break;
        default: //parent
            for (i = 0; i < BUFFER_SIZE; i++)
            {
                //usleep(100);
                shm = shmat(shmid, 0, 0);
                *shared = num(i);

                printf("Producer creates ");
                printf("['%c'] ", *shared);
                printf("at index [%d]\n", i);
                printf("\n");
                fflush(stdout);

                sem_op.sem_num = 0;
                sem_op.sem_op = 1;
                sem_op.sem_flg = 0;
                semop(sem_set_id, &sem_op, 1);

                if (rand() > 3 *(RAND_MAX/4))
                {
                    delay.tv_sec = 0;
                    delay.tv_nsec = 10;
                    nanosleep(&delay, NULL);
                }
            }
            break;
    }

    return 0;
}

int num(int i)
{   
    i = rand() % (90 - 65) + 65;

    return i;
}

1 个答案:

答案 0 :(得分:3)

当您使用fork时,每个变量都会复制到每个流程 - 即每个流程都有自己已定义变量的副本 - 并且新变量与流程相关。所以,你不能简单地共享内存。

在你的情况下,你在数组中写入并读入另一个未初始化的数组,因为每个进程(子进程和父进程)都有自己的内存。

看看:How to share memory between process fork()?它将向您解释如何在使用fork(shm_open()shm_unlink()mmap()等创建的进程之间使用共享内存。

修改

通过阅读您的代码,标题和问题,您可以通过2种方式在子级和父级之间共享数据。所以你有两个选择:

  • 使用共享内存和信号量:数组在进程之间共享,信号量确保您可以读取或写入共享数组的某些部分。无需readwritefd
  • 或使用竖管:不需要共享内存和信号量,只需使用管道,即fd readwrite

选择1

mmap的第一个参数与malloc非常相似。所以在你的数组中你应该有类似的东西:

...
char * glob_array = mmap(NULL, sizeof(char) * BUFFER_SIZE, PROT_READ | PROT_WRITE, 
                MAP_SHARED | MAP_ANONYMOUS, -1, 0);

child_pid = fork();

....

现在,您可以在子级和父级中使用glob_array。在这种情况下,请勿使用readwritefd,数据可直接在glob_array中使用(即如果您需要第一个数据,请使用{{1}直接,glob_array[0]为秒等等)。此外,信号量可确保您同时进行读/写。

选择2

通过重新阅读你的代码,我想我会传递一些东西:你可能想用read和write来传递从child到parent的值。所以你需要管道。在您粘贴的原始代码上,在glob_array[1]之前移动fd的声明并初始化管道:

fork

如果没有共享数组,它将工作;)同时读入管道将阻塞,直到数据可用,因此,您不需要信号量。