c - 如何使用管道或任何其他方法将数据从多个子进程发送到父数组?
问题描述
我正在尝试通过创建多个进程fork()
并对子进程进行一些数学运算,例如数组元素的总和,然后将值返回给父进程,父进程会将每个值保存parentArray
在代码中。现在我的问题是如何在这个阶段做到这一点,我只收到第一个进程的一个值,其余值为零。是否有另一种传递价值的方式,或者可以通过管道完成?请帮我
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
void showReturnStatus(pid_t childpid,int status){
if (WIFEXITED(status) && !WEXITSTATUS(status))
printf("Child %ld terminated normally\n", (long)childpid);
else if (WIFEXITED(status))
printf("Child %ld terminated with return status %d\n",(long)childpid, WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("Child %ld terminated due to uncaught signal %d\n",(long)childpid, WTERMSIG(status));
else if (WIFSTOPPED(status))
printf("Child %ld stopped due to signal %d\n",(long)childpid, WSTOPSIG(status));
}
int main(int argc, char *argv[])
{
srand(time(0));
int arraySize=9,noProcess=3,array[arraySize],status=0;
pid_t pid;
int parentSum=0;
int parentArray[3],fd[2]; //fd file descriptor
if(pipe(fd)==-1)
return 0;
for(int i=0 ;i<arraySize;i++)
array[i]=(rand()%100)+1;
for(int i=0;i<arraySize;i++){
printf("\n %d : %d ",i,array[i]);
}
printf("\nParent PID[%d] \n",getpid());
for(int childP=0;childP<noProcess;childP++){
int child=fork();
int childSum;
if(child==0){
close(fd[0]);
childSum=0.0;
for(int i=childP*3;i<(childP+1)*3;i++)
childSum+=array[i];
printf("\nChild Process No [%d] PID [%d] Return Sum : %d \n",childP,getpid(),childSum);
write(fd[1],&childSum,sizeof(childSum));
close(fd[1]);
exit(0);
}
pid=wait(&status);
showReturnStatus(pid,status);
close(fd[1]);
read(fd[0],parentArray,sizeof(parentArray));
close(fd[0]);
}
for (int i=0;i<3;i++)
{
printf("\nValue Array : %d\n",parentArray[i]);
}
printf("\nParent Process with PID [%d] calculate Sum : %d\n",getppid());
return 0;
}
解决方案
这是您的代码的修订版本,其中包含多项更改。
它允许子进程同时运行。
它关注各种错误情况。
它每行打印 10 个数据条目。
它检查数组大小是进程数的整数倍。
它不会在父节点中过早关闭管道。
它将错误报告给标准错误,并以失败状态退出。
它在输出消息的末尾打印换行符;它不需要在消息的开头打印换行符。
我宁愿避免
noProcess
,因为它暗示“没有过程”;我重命名了它numProcess
。该代码使用
numProcess
andarraySize
来控制所有相关的循环等。它在父进程中计算并打印总和,以便可以快速检查来自子进程的值。这也表明,出于本练习的目的,使用流程是一种人工制品。
它打印每行具有多个条目的数组。
我调整了计算以生成数字 1..99,以便格式
%2d
统一工作。我使用这些选项(源代码
pipe79.c
、程序pipe79
)进行编译:gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes pipe79.c -o pipe79
测试
argc > 0
只是为了确保它argc
被使用——如果不是,代码由于未使用的变量而无法编译。我介绍了变量
numPerProcess
,start
并且stop
因为这些值至少被使用了两次。除了将其设置为静态之外,我不需要进行
showReturnStatus()
任何修改,这又是必要的,因为我使用了编译选项。static
该函数不在此源文件之外使用,因此 IMO无论如何都应该使用它。如果它在其他地方使用,它将在一个标题中声明,该标题将包含在定义它的位置和使用它的位置。可能还有其他可以指出的详细更改,但我忘记了我进行了更改。
代码:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
static void showReturnStatus(pid_t childpid, int status)
{
if (WIFEXITED(status) && !WEXITSTATUS(status))
printf("Child %ld terminated normally\n", (long)childpid);
else if (WIFEXITED(status))
printf("Child %ld terminated with return status %d\n", (long)childpid, WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("Child %ld terminated due to uncaught signal %d\n", (long)childpid, WTERMSIG(status));
else if (WIFSTOPPED(status))
printf("Child %ld stopped due to signal %d\n", (long)childpid, WSTOPSIG(status));
}
int main(int argc, char *argv[])
{
srand(time(0));
int arraySize = 72;
int numProcess = 6;
int array[arraySize];
int fd[2];
const char *arg0 = (argc == 0) ? "pipe79" : argv[0]; /* Use argc */
assert(arraySize % numProcess == 0);
int numPerProcess = arraySize / numProcess;
if (pipe(fd) == -1)
{
fprintf(stderr, "%s: failed to create a pipe\n", arg0);
exit(EXIT_FAILURE);
}
int sum = 0;
for (int i = 0; i < arraySize; i++)
{
array[i] = (rand() % 99) + 1;
sum += array[i];
}
int width = 0;
const char *pad = "";
for (int i = 0; i < arraySize; i++)
{
width += printf("%s%2d: %2d", pad, i, array[i]);
pad = ", ";
if (width > 72)
{
putchar('\n');
width = 0;
pad = "";
}
}
if (width > 0)
putchar('\n');
printf("Sum calculated by parent: %d\n", sum);
printf("Parent PID[%d]\n", getpid());
for (int childP = 0; childP < numProcess; childP++)
{
int child = fork();
if (child < 0)
{
fprintf(stderr, "%s: failed to fork child %d\n", arg0, childP + 1);
exit(EXIT_FAILURE);
}
if (child == 0)
{
close(fd[0]);
int childSum = 0;
int start = childP * numPerProcess;
int stop = start + numPerProcess;
printf("Child PID %d: processing rows %d..%d\n", getpid(), start, stop - 1);
for (int i = start; i < stop; i++)
childSum += array[i];
printf("Child Process No [%d] PID [%d] Return Sum : %d\n", childP, getpid(), childSum);
if (write(fd[1], &childSum, sizeof(childSum)) != sizeof(childSum))
{
fprintf(stderr, "Child Process No [%d] PID [%d] failed to write to the pipe\n",
childP, getpid());
exit(EXIT_FAILURE);
}
close(fd[1]);
exit(0);
}
}
close(fd[1]);
sum = 0;
pid_t pid;
int status = 0;
while ((pid = wait(&status)) != -1)
{
int number;
showReturnStatus(pid, status);
if (read(fd[0], &number, sizeof(number)) != sizeof(number))
{
fprintf(stderr, "%s: parent process got a short read on the pipe\n", arg0);
exit(EXIT_FAILURE);
}
printf("sum from pipe: %d\n", number);
sum += number;
}
printf("Parent Process with PID [%d] accumulated sum : %d\n", getpid(), sum);
return 0;
}
样本输出:
0: 68, 1: 13, 2: 74, 3: 37, 4: 88, 5: 4, 6: 73, 7: 94, 8: 2, 9: 71
10: 20, 11: 19, 12: 93, 13: 96, 14: 13, 15: 96, 16: 98, 17: 12, 18: 94, 19: 10
20: 27, 21: 38, 22: 48, 23: 14, 24: 18, 25: 50, 26: 61, 27: 15, 28: 88, 29: 41
30: 2, 31: 99, 32: 42, 33: 8, 34: 55, 35: 32, 36: 29, 37: 53, 38: 78, 39: 15
40: 69, 41: 19, 42: 85, 43: 78, 44: 3, 45: 59, 46: 96, 47: 37, 48: 35, 49: 95
50: 59, 51: 12, 52: 63, 53: 34, 54: 31, 55: 17, 56: 88, 57: 63, 58: 74, 59: 15
60: 10, 61: 38, 62: 24, 63: 27, 64: 70, 65: 64, 66: 40, 67: 43, 68: 87, 69: 82
70: 35, 71: 11
Sum calculated by parent: 3451
Parent PID[58056]
Child PID 58057: processing rows 0..11
Child Process No [0] PID [58057] Return Sum : 563
Child PID 58058: processing rows 12..23
Child Process No [1] PID [58058] Return Sum : 639
Child PID 58059: processing rows 24..35
Child Process No [2] PID [58059] Return Sum : 511
Child PID 58060: processing rows 36..47
Child Process No [3] PID [58060] Return Sum : 621
Child PID 58061: processing rows 48..59
Child Process No [4] PID [58061] Return Sum : 586
Child 58059 terminated normally
sum from pipe: 563
Child 58060 terminated normally
sum from pipe: 639
Child 58058 terminated normally
sum from pipe: 511
Child 58057 terminated normally
sum from pipe: 621
Child 58061 terminated normally
sum from pipe: 586
Child PID 58062: processing rows 60..71
Child Process No [5] PID [58062] Return Sum : 531
Child 58062 terminated normally
sum from pipe: 531
Parent Process with PID [58056] accumulated sum : 3451
推荐阅读
- node.js - How to run the IPFS example below in node?
- javascript - 带点的混合字母数字字符串的排序列表?
- angular - Angular - 使用异步管道时如何检查 *ngFor 中数组的长度?
- javascript - 如何在循环时将事物放入数组中进行偏移
- linux - 将 kubernetes 状态指标 curl 响应单位转换为兆字节
- excel - 选择项目后,鼠标悬停事件不会重新触发
- reactjs - 在 React 中向 iFrame 发送表单响应
- css - 覆盖 Google recaptcha 的样式
- heroku - 状态从开始变为崩溃
- sql - T-SQL:你能将循环中的查询结果连接到一个表中吗?