Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 用于多进程的管道_C_Pipe_Fork - Fatal编程技术网

C 用于多进程的管道

C 用于多进程的管道,c,pipe,fork,C,Pipe,Fork,目前正在做一些家庭作业,日子不好过。目标是生成100000个数字,并通过将工作划分为10个过程(每个过程10000个数字)将它们相加 我想我已经找到了分叉进程的方法(希望如此),但是使用Pipe()传递每个子进程的小计是行不通的。。。下面的程序为每个子进程返回44901,为运行总数返回449010 我正在努力奋斗,但我觉得这是一件简单的事情,我应该能够理解 main() { int i; pid_t pid; int status = 0; int fd[2];

目前正在做一些家庭作业,日子不好过。目标是生成100000个数字,并通过将工作划分为10个过程(每个过程10000个数字)将它们相加

我想我已经找到了分叉进程的方法(希望如此),但是使用Pipe()传递每个子进程的小计是行不通的。。。下面的程序为每个子进程返回44901,为运行总数返回449010

我正在努力奋斗,但我觉得这是一件简单的事情,我应该能够理解

main()
{
    int i;
    pid_t pid;
    int status = 0;
    int fd[2];
    int runningTotal = 0;
    pipe(fd);

    int t;
    int r;

    for (i = 0; i < 10; i++) {
        pid = fork();
        if (pid == 0){
            close(fd[0]);
            t = ChildProcess();
            write(fd[1], &t, sizeof(t));
            exit(0);
        }
        close(fd[1]);
        read(fd[0], &r, sizeof(r));
        runningTotal = runningTotal + r;
        wait(&status);
    }

    printf("%i\n", runningTotal);
}

int ChildProcess() {
    int i;
    int total = 0;
    int r = 0;

    for (i = 0; i < 10000; i++) {
        r = rand() % 10; // 0 to 10
        total = total + r;
    }

    printf("%i\n", total);
    return total;
}
main()
{
int i;
pid_t pid;
int status=0;
int-fd[2];
int runningTotal=0;
管道(fd);
int t;
INTR;
对于(i=0;i<10;i++){
pid=fork();
如果(pid==0){
关闭(fd[0]);
t=ChildProcess();
写入(fd[1],&t,sizeof(t));
出口(0);
}
关闭(fd[1]);
读取(fd[0],&r,sizeof(r));
runningTotal=runningTotal+r;
等待(&状态);
}
printf(“%i\n”,runningTotal);
}
int ChildProcess(){
int i;
int-total=0;
int r=0;
对于(i=0;i<10000;i++){
r=rand()%10;//0到10
总计=总计+r;
}
printf(“%i\n”,总计);
返回总数;
}
初始诊断
如果您担心的是子对象都产生相同的值,那么问题是它们都使用相同的随机序列,因为您没有在任何地方调用
srand()
。你需要叫它,每个孩子有不同的种子

它不是100%可靠的,但您可能会通过
srand(time(0)+getpid())逃脱
在每个子项中,甚至只是
getpid()
,因为这些值保证是不同的

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

int ChildProcess(void)
{
    int total = 0;
    srand(time(0) + getpid());

    for (int i = 0; i < 10000; i++)
    {
        int r = rand() % 10; // 0 to 9 (not 10).
        total = total + r;
    }

    printf("%i\n", total);
    return total;
}
#包括
#包括
#包括
#包括
int子进程(void)
{
int-total=0;
srand(时间(0)+getpid());
对于(int i=0;i<10000;i++)
{
int r=rand()%10;//0到9(不是10)。
总计=总计+r;
}
printf(“%i\n”,总计);
返回总数;
}
进一步审查 事实上,仔细检查,还有另一个问题。父进程在分叉第一个子进程后关闭管道的写入端,因此后续子进程没有可用的文件描述符可供使用。读取值将始终是来自第一个子级的值。所以,你需要做更认真的工作

int main(void)
{
    int fd[2];
    pipe(fd);  // Missing error check

    for (int i = 0; i < 10; i++) {
        pid_t pid = fork();
        if (pid == 0){
            close(fd[0]);
            int t = ChildProcess();
            write(fd[1], &t, sizeof(t));  // Missing error check?
            exit(0);
        }
        // Print PID here?  Error check?
    }

    close(fd[1]);

    int r;
    int runningTotal = 0;
    while (read(fd[0], &r, sizeof(r)) > 0)  // Debugging opportunities here
        runningTotal = runningTotal + r;

    while (wait(0) > 0)  // Lots of debugging opportunities here
        ;

    printf("%i\n", runningTotal);
    return 0;
}
int main(无效)
{
int-fd[2];
管道(fd);//缺少错误检查
对于(int i=0;i<10;i++){
pid_t pid=fork();
如果(pid==0){
关闭(fd[0]);
int t=ChildProcess();
写入(fd[1],&t,sizeof(t));//是否缺少错误检查?
出口(0);
}
//在这里打印PID?错误检查?
}
关闭(fd[1]);
INTR;
int runningTotal=0;
while(读取(fd[0],&r,sizeof(r))>0)//这里的调试机会
runningTotal=runningTotal+r;
while(wait(0)>0)//这里有很多调试机会
;
printf(“%i\n”,runningTotal);
返回0;
}

通常,每个孩子都会使用一个单独的管道,否则家长不可能知道读取的数据来自哪个进程。我不认为这是一个很重要的问题,因为在这里,你其实不在乎。尽管这仍然让我有点畏缩,但我认为你确实可以通过一根管子来完成这项特殊任务

事实上,我认为你的问题根本不在于管道。它与
rand()
一起使用。所有子进程都计算完全相同的(伪)随机数序列,因为它们都使用相同的(默认)种子。如果要生成不同的数字序列,则需要在每个子进程中调用
srand()
,在每个子进程中提供不同的种子。将生成的编号序列
rand()
完全由其开始的种子决定

还要注意的是,如果系统的随机数生成器非常好,那么由各个进程计算的所有和应该彼此非常接近,并且与您报告的结果非常接近。这是统计学中中心极限定理的一个结果,但你可以简单地把它看作是较大的结果平均平衡较小的结果。在计算10模的余数时,可能会产生轻微的偏差。

鉴于此代码:(摘自发布代码)

(i=0;i<10;i++)的
{
pid=fork();
如果(pid==0){
关闭(fd[0]);
t=ChildProcess();
写入(fd[1],&t,sizeof(t));
出口(0);
}
关闭(fd[1]);
读取(fd[0],&r,sizeof(r));
runningTotal=runningTotal+r;
等待(&状态);
}
有一个顺序问题

当父循环在循环的第一次迭代中关闭fd[1]时,该文件描述符不会在循环的下一次迭代中“神奇地”再次打开


循环中的父级代码需要检查调用
read()
返回的值,以确保操作成功。(在循环的第一次迭代之后,它可能没有成功,因此变量“r”将保持不变。

第一条规则:当问题中的值为100k时,先用100(或可能1000)进行演示;得到工作的岩石实体。然后考虑乘以1000(或100)。如果您关心的是所有子项都产生相同的值,那么问题是它们都使用相同的随机序列,因为您不在任何地方调用
srand()
。您需要为每个子项调用一次,每个子项使用不同的种子。main()的声明函数始终返回“int”。编译器应该对此问题进行投诉。始终在启用所有警告的情况下编译(对于gcc,至少使用:
-Wall-Wextra-pedantic
)在发布代码时修复警告,特别是在询问运行时
for (i = 0; i < 10; i++) {
    pid = fork();
    if (pid == 0){
        close(fd[0]);
        t = ChildProcess();
        write(fd[1], &t, sizeof(t));
        exit(0);
    }
    close(fd[1]);
    read(fd[0], &r, sizeof(r));
    runningTotal = runningTotal + r;
    wait(&status);
}