将字符数组从 parent 传递到 child
Passing char array from parent to child
这是我第一次在这里发帖。我是 OS 编程新手。
所以我有这个程序,我在网上找到并决定修改它。 parent 创建一个包含随机字母的字符数组。这封信被传递给 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]
EDIT1
我使用共享内存。 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
时,每个变量都被复制到每个进程 - 即每个进程都有自己的已定义变量副本 - 并且新变量依赖于进程。所以,你不能像那样简单地共享内存。
在您的情况下,您写入一个数组并读取另一个未初始化的数组,因为每个进程(child 和 parent)都有自己的内存。
看看:How to share memory between process fork()? 它会向您解释如何在用 fork 创建的进程之间使用共享内存(shm_open()
、shm_unlink()
、mmap()
等.).
编辑
通过阅读您的代码、标题和问题,您可以混合使用 2 种方式在 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();
....
您现在可以在 child 和 parent 中使用 glob_array
。在这种情况下,不要使用read
或write
和fd
,数据直接在glob_array
中可用(即如果您需要第一个数据,请使用glob_array[0]
直接,glob_array[1]
第二个等等)。此外,信号量确保您同时 read/write.
选项 2
通过 re-reading 你的代码,我想我传递了一些东西:你可能想使用读取和写入来将值从 child 传递到 parent。所以你需要管道。在您粘贴的原始代码上,将 fd
的声明移动到 fork
之前并初始化管道 :
int fd[2];
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
child_pid = fork();
无需共享数组也能正常工作 ;) 另外,读入管道将阻塞直到数据可用,因此,您不需要信号量。
这是我第一次在这里发帖。我是 OS 编程新手。
所以我有这个程序,我在网上找到并决定修改它。 parent 创建一个包含随机字母的字符数组。这封信被传递给 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]
EDIT1 我使用共享内存。 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
时,每个变量都被复制到每个进程 - 即每个进程都有自己的已定义变量副本 - 并且新变量依赖于进程。所以,你不能像那样简单地共享内存。
在您的情况下,您写入一个数组并读取另一个未初始化的数组,因为每个进程(child 和 parent)都有自己的内存。
看看:How to share memory between process fork()? 它会向您解释如何在用 fork 创建的进程之间使用共享内存(shm_open()
、shm_unlink()
、mmap()
等.).
编辑
通过阅读您的代码、标题和问题,您可以混合使用 2 种方式在 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();
....
您现在可以在 child 和 parent 中使用 glob_array
。在这种情况下,不要使用read
或write
和fd
,数据直接在glob_array
中可用(即如果您需要第一个数据,请使用glob_array[0]
直接,glob_array[1]
第二个等等)。此外,信号量确保您同时 read/write.
选项 2
通过 re-reading 你的代码,我想我传递了一些东西:你可能想使用读取和写入来将值从 child 传递到 parent。所以你需要管道。在您粘贴的原始代码上,将 fd
的声明移动到 fork
之前并初始化管道 :
int fd[2];
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
child_pid = fork();
无需共享数组也能正常工作 ;) 另外,读入管道将阻塞直到数据可用,因此,您不需要信号量。