这是我第一次在这里发帖。我是操作系统编程的新手。
所以我有这个我在网上找到的程序并决定修改它。父级创建一个包含随机字母的 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 之间共享数据。所以你有两个选择:
- 使用共享内存和信号量:数组在进程之间共享,信号量确保您可以读取或写入共享数组的某些部分。无需
read
、write
和fd
- 或者使用管道:不需要共享内存和信号量,只需使用管道,即
fd
read
和write
。
选择 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
。在这种情况下,不要使用read
或write
和fd
,数据直接在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/