这是我第一次在这里发帖。我是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;
}
答案 0 :(得分:3)
当您使用fork
时,每个变量都会复制到每个流程 - 即每个流程都有自己已定义变量的副本 - 并且新变量与流程相关。所以,你不能简单地共享内存。
在你的情况下,你在数组中写入并读入另一个未初始化的数组,因为每个进程(子进程和父进程)都有自己的内存。
看看:How to share memory between process fork()?它将向您解释如何在使用fork(shm_open()
,shm_unlink()
,mmap()
等创建的进程之间使用共享内存。
修改强>
通过阅读您的代码,标题和问题,您可以通过2种方式在子级和父级之间共享数据。所以你有两个选择:
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
中使用(即如果您需要第一个数据,请使用{{1}直接,glob_array[0]
为秒等等)。此外,信号量可确保您同时进行读/写。
选择2
通过重新阅读你的代码,我想我会传递一些东西:你可能想用read和write来传递从child到parent的值。所以你需要管道。在您粘贴的原始代码上,在glob_array[1]
之前移动fd
的声明并初始化管道:
fork
如果没有共享数组,它将工作;)同时读入管道将阻塞,直到数据可用,因此,您不需要信号量。