[英]LINUX IPC: Passing different values to CHILD process using PIPE not working, except for first time, in C
我有一组taskid分为几组,每组由唯一的groupid
标识。
对于每个group
,我需要生成一个子进程( 每个进程都充当服务器-意味着它们从其他进程获取消息并在处理后返回结果 )。
每个孩子都有权为其与其关联的GROUP
专门服务。 因此,我想在生成后立即将唯一的groupId
传递给每个子进程,以便它仅执行与其groupId
相关联的任务。
在CHILD产生时,PARENT仅向CHILD写入了groupId
,也只有一次。 CHILD不应该将任何内容写回PARENT。 (单向通信- PARENT - write/CHILD -read
)
经过一些研究,我编写了如下的伪代码。 (这是一个可编译的代码)。
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<time.h>
#include<sys/wait.h>
int process(int n);
#define NGROUPID 5
#define INIT_GROUPID 1000
int parent_to_child[2];
int main()
{
pid_t pid;
pid_t pid_array[NGROUPID]; //Child pid array.
int groupId[NGROUPID];
int groupID = 0,i;
srand((unsigned int) time(NULL)); //random seed
groupId[0] = INIT_GROUPID;
printf("[0.1] ");
//set groupIds
for(i=1; i < (NGROUPID - 1); i++)
{
int j = i -1;
groupId[i]= groupId[j] + 2;
printf("%d~%d\t",j,groupId[j]);
}
printf("%d~%d\n",i-1,groupId[i-1]);
fflush(stdout); //Flushing stdout before pipe call
pipe(parent_to_child);
// For each groupId, spawn child process
for (i = 0; i < (NGROUPID - 1); i++ )
{
pid = fork();
if(pid < 0)
{
perror("fork failed\n");
exit(1);
}
if(pid == 0)
{
process(i); //Child Process.
break; //Is it necessory to break? Will it create Children of children?
}
if(pid > 0)
{
close(parent_to_child[0]); //parent is not reading from child
printf("[1.1] writing to child: %d parent %d i %d groupId %d\n",pid,getpid(),i,groupId[i]);
write(parent_to_child[1], &groupId[i], sizeof(int)); //Passing groupId to Child.
pid_array[i] = pid; //To shutdown cleanly.
}
}
if(pid > 0)
{
for (i = 0; i < (NGROUPID - 1); i++ )
{
printf("[1.2] waiting for pid: %d\n",pid_array[i]);
waitpid(pid_array[i], NULL, 0);
printf("[1.3] Finished pid: %d\n",pid_array[i]);
}
}
printf("[0.2] Did we Finished total %d PID %d\n", NGROUPID, getpid());
if(pid > 0)
printf("[1.4] There are no zombies\n");
return 0;
}
//This is a pseudo code. Actual code will consists of receiving messages
// from other processes (using message queue) and return the results after processing.
// This act like a SERVER process, which will not quit in usual scenario.
int process(int n)
{
int groupID = 0;
close(parent_to_child[1]); //we are not going to return to Parent.
read(parent_to_child[0], &groupID, sizeof(int)); //Read from Parent
unsigned int sec = (rand() % 10) + 1;
printf("[2.1] Processing %d th Process pid: %d groupId %d sleep %d sec\n",n, getpid(), groupID, sec);
sleep(sec);
printf("[2.2] Returning from sleep %d Process pid: %d groupId %d sleep %d sec\n",n, getpid(), groupID, sec);
}
该程序的输出如下:
[0.1] 0~1000 1~1002 2~1004 3~1006
[1.1] writing to child: 15068 parent 15067 i 0 groupId 1000
[2.1] Processing 0 th Process pid: 15068 groupId 1000 sleep 3 sec
[1.1] writing to child: 15069 parent 15067 i 1 groupId 1002
[2.1] Processing 1 th Process pid: 15069 groupId 0 sleep 3 sec
[1.1] writing to child: 15070 parent 15067 i 2 groupId 1004
[2.1] Processing 2 th Process pid: 15070 groupId 0 sleep 3 sec
[1.1] writing to child: 15071 parent 15067 i 3 groupId 1006
[1.2] waiting for pid: 15068
[2.1] Processing 3 th Process pid: 15071 groupId 0 sleep 3 sec
// This Gap is not a part of output. It indicates the sleep worked from here.
[2.2] Returning from sleep 0 Process pid: 15068 groupId 1000 sleep 3 sec
[0.2] Did we Finished total 5 PID 15068
[2.2] Returning from sleep 1 Process pid: 15069 groupId 0 sleep 3 sec
[0.2] Did we Finished total 5 PID 15069
[1.3] Finished pid: 15068
[1.2] waiting for pid: 15069
[1.3] Finished pid: 15069
[1.2] waiting for pid: 15070
[2.2] Returning from sleep 2 Process pid: 15070 groupId 0 sleep 3 sec
[0.2] Did we Finished total 5 PID 15070
[1.3] Finished pid: 15070
[1.2] waiting for pid: 15071
[2.2] Returning from sleep 3 Process pid: 15071 groupId 0 sleep 3 sec
[0.2] Did we Finished total 5 PID 15071
输出中的编号系统如下。
[0.*] - Indicate that Print from General part of code (neither parent or child)
[1.*] - Indicate that Print from PARENT process. (pid > 0)
[2.*] - Indicate that Print from CHILD process. (pid == 0)
此代码几乎没有问题。
1.随机数我依靠随机数来为儿童产生不均匀的睡眠时间,这模仿了实际情况。 即使我在main
函数中放置了srand(time(NULL))
函数,但process() function
中的rand()
始终生成相同的输出(在上面的输出中为3 seconds
)。 是因为CPU太快了吗? 如果是,是否有更好的种子可用?
2.阅读PIPE
除非第一次,从CHILD进程读取的groupId
始终为零。 如下面的输出所示。
[2.1] Processing 2 th Process pid: 15070 groupId 0 sleep 3 sec
您可以清楚地看到,在由父代进行write
, groupId
被正确拾取。 (如下所示):
[1.1] writing to child: 15070 parent 15067 i 2 groupId 1004
我如何改进此代码以实现结果。 还是这种逻辑有任何缺陷(我问这个问题是因为我是IPC的初学者,没有太多的经验)。 我是否需要为groupId
数组实现一个critical section
?
提前致谢。
随机数。 您在分叉之前先叫srand
,所以所有子代都继承相同的种子,因此他们对rand
的调用将产生相同的数字。 您可以在循环内增加种子,并使每个子代自己调用srand
。
通讯。 父parent_to_child[0]
在生成第一个孩子后关闭parent_to_child[0]
,因此以后的孩子将继承封闭的管道,并且无法通过它接收groupID
信息。 仅当所有分叉完成时,父级才应关闭该管道。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.