c - 将字符数组从父级传递给子级

标签 c pipe semaphore

这是我第一次在这里发帖。我是操作系统编程的新手。

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

我无法从 child 那里取回这封信。我得到了一些东西,但它们不是正确的字母。

#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]

编辑1 我使用共享内存。 child 只识别 parent 添加到数组中的最后一个字母并重复它。

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

最佳答案

当您使用fork 时,每个变量都被复制到每个进程——即每个进程都有自己的已定义变量副本——并且新变量依赖于进程。所以,你不能像那样简单地共享内存。

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

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

编辑

通过阅读您的代码、标题和问题,您可以混合使用两种方式在 child 和 parent 之间共享数据。所以你有两个选择:

  • 使用共享内存和信号量:数组在进程之间共享,信号量确保您可以读取或写入共享数组的某些部分。无需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中可用(即如果您需要第一个数据,请直接使用 glob_array[0],第二个使用 glob_array[1],依此类推)。此外,信号量确保您同时读/写。

选择 2

通过重新阅读您的代码,我想我忽略了一些东西:您可能想使用读取和写入来将值从子项传递到父项。所以你需要管道。在您粘贴的原始代码上,将 fd 的声明移动到 fork 之前并初始化管道:

int fd[2];

if (pipe(pipefd) == -1) {       
    perror("pipe");
    exit(EXIT_FAILURE);
}

child_pid = fork();

无需共享数组也能正常工作 ;) 此外,在管道中读取数据会阻塞,直到数据可用,因此,您不需要信号量。

关于c - 将字符数组从父级传递给子级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35935591/

上一篇:与结构和指针混淆

下一篇:C 函数 fork()

相关文章:

c - 我的大部分程序都是分开的,只是无法将所有内容组合在一起

c - 在 C 上使用 OpenMP 并行一段时间

c - 我们如何用 Xlib/C 模拟鼠标点击?

linux - 使管道的左侧在右侧终止时终止

c - 子进程和父进程之间的 POSIX 信号量

c++ - 如何从不断更新的文件中读取和提取信息?

c - 在我自己的简单 shell 中进行管道传输和重定向

c - 如何在 Linux 中使用 C 中的多个管道运行命令?

ios - 在这个 "starts busy"推测处理场景中使用 DispatchSemaphore

c - 在c中使用pthreads,出于某种原因,每个pthread都有一个不同的锁实例