LinuxIPC:使用管道向子进程传递不同的值不起作用,C中第一次除外
我有一组TaskID,分为几个组,每个组由一个唯一的groupid标识 对于每个组,我需要生成一个子进程,每个子进程都充当服务器——这意味着它们从其他进程获取消息,并在处理后返回结果 每个儿童都有权专门为与其相关的群体服务。因此,我希望在生成后立即将唯一的groupId传递给每个子进程,以便它只执行与其groupId相关联的任务 只有父对象向子对象写入groupId,在子对象生成时也只有一次。孩子不应该给父母写任何东西。单向通信-父级-写入/子级-读取 经过一点研究,我编写了一个伪代码,如下所示。这是一个可编译的代码LinuxIPC:使用管道向子进程传递不同的值不起作用,C中第一次除外,c,linux,ipc,C,Linux,Ipc,我有一组TaskID,分为几个组,每个组由一个唯一的groupid标识 对于每个组,我需要生成一个子进程,每个子进程都充当服务器——这意味着它们从其他进程获取消息,并在处理后返回结果 每个儿童都有权专门为与其相关的群体服务。因此,我希望在生成后立即将唯一的groupId传递给每个子进程,以便它只执行与其groupId相关联的任务 只有父对象向子对象写入groupId,在子对象生成时也只有一次。孩子不应该给父母写任何东西。单向通信-父级-写入/子级-读取 经过一点研究,我编写了一个伪代码,如下所示
#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.*] - 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)
对于这段代码,我面临的问题很少
一,。随机数
我依靠随机数来产生孩子们不均衡的睡眠时间,这与实际情况类似。尽管我已经在主函数中添加了srandtimeNULL函数,但是进程函数中的rand总是在上面的输出中生成相同的输出3秒。是不是因为CPU太快了??。如果有,有更好的种子吗
二,。阅读管
除非是第一次,否则从子进程读取的groupID始终为零。如以下输出所示
[2.1]处理第二个进程pid:15070 groupId 0睡眠3秒
您可以清楚地看到,在父级写入时,正确地拾取了groupId。如下所示:
[1.1]写信给孩子:15070家长15067 i 2组ID 1004
如何改进此代码以获得结果。或者在这个逻辑中有什么缺陷吗?我问这个问题是因为我是IPC的初学者,之前没有太多经验。我是否需要为groupId阵列实现一个关键部分
提前感谢。随机数。在fork之前调用srand,因此所有子级都继承相同的种子,因此它们对rand的调用将生成相同的数字。您可以在循环内增加种子数,并让每个子项单独调用srand
沟通。父级在生成第一个子级后关闭父级到子级[0],因此以后的子级将继承一个关闭的管道,并且无法通过它接收groupID信息。只有在所有分叉完成后,家长方可关闭该管道。您的错误检查在哪里?管道、写入、读取、等待PID等都可能失败。读/写可以读/写的数据比请求的少。也许你应该检查更多库调用的返回值,看看它们是否成功。注意rand是一个伪随机数生成器PRNG:它实际上是确定性的,而不是真正的随机数,因此当给定相同的种子并调用相同的次数后,它总是给出相同的结果。而分叉进程肯定会从相同的状态开始。您可以在子进程中使用srandtimeNULL+getpid之类的东西来为每个进程获取不同的种子。此行:pipeparent\u to\u child;仅创建一个管道。家长“盲目”地向那条管道写信。任何人都可以猜测哪个子进程将访问/读取该管道。建议为每个子级生成单独的管道。注意:此语句:closeparent_to_child[0];将在第一次迭代后失败。
[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)