如何从子进程获取返回值?

12

该程序计算从1到N的数字总和。 子进程计算偶数的总和。 父进程计算奇数的总和。 我想在父进程中获取子进程的返回值。如何实现?

#include<stdio.h>
#include<errno.h>
#include<unistd.h>
#include<stdlib.h>
#include<fcntl.h>

int main()
{
    int N;
    int id;
    int fd_result;;

    printf("Enter N till which you want the sum: \n");
    scanf("%d",&N);
    if ((fd_result=creat("result", 600))== -1)
    {
        perror("Error creating file");
        exit(1);
    }
    if ((fd_result=open("result",O_TRUNC | O_RDWR)) == -1)
    {
        perror("Error Opening file");
        exit(1);
    }
    if ((id=fork())<0)
    {
        perror("Error occurred forking....!");
        exit(errno);
    }
    if (id == 0)
    {
        int i;
        int sum=0;
        for (i=0;i<=N;i=i+2)
            sum+=i;
        printf("Child sum: %d",sum);
        if (write(fd_result,&sum,sizeof(int))==-1) perror("Error writing to file");
        _exit(0);
    }


    if (id > 0)
    {
        int i;
        int sum=0;
        int sum_odd;
        for (i=1;i<=N;i=i+2)
            sum+=i;
        lseek(fd_result,0,SEEK_SET);
        read(fd_result,&sum_odd,sizeof(int));
        printf("\nThe sum is: %d",sum+(int)sum_odd);
    }

    close(fd_result);
    return 0;
}
请告诉我如何获取子进程的返回值?
5个回答

10

1
我该如何实际使用它?我无法理解。实际上,这是我第一次编写fork()程序...请帮忙。 - shadyabhi
在父进程中调用 waitpid(-1, &status, 0); - Diego Torres Milano

6

简而言之:

int wstatus;
waitpid(<pid>, &wstatus, 0); // Store proc info into wstatus
int return_value = WEXITSTATUS(wstatus); // Extract return value from wstatus

参考资料

waitpid的man页面显示其类型签名为:

pid_t waitpid(pid_t pid, int *stat_loc, int options);

文档还指出,我们可以使用stat_loc参数存储进程信息:

如果stat_loc参数的值不是空指针,则应在指向的位置中存储信息。

stat_loc参数是由stat_val指向的整数值。

然后我们使用WEXITSTATUS(wstatus)从进程中提取返回值。

WEXITSTATUS(stat_val): 如果WIFEXITED(stat_val)的值为非零,则该宏将计算子进程传递给_exit()或exit()的状态参数的低8位,或者子进程从main()函数返回的值。


2

哎呀!这不是bash!无论如何...

生成进程的原因是为了继续主要流程,同时做一些不影响主要流程的事情。我正在遍历10k个图像目录,并移出重复项。我将比较代码放入一个函数和子进程中。它非常快。

获取值的方法是创建一个管道,将值回显到该管道上,然后读取管道:(警告!以下代码可能不起作用,它只是展示一个可行的管道)

mkfifo pipe
moved=0
# Use imageMagick 'compare' to find files with zero difference:
comPare () { 
 if [[ ! $(compare -metric AE $1 $2) ]]; then 
    mv $2 moved;
    echo 1 > pipe;
  else echo 0 > pipe
  fi
}

# For every file in the dir, compare it to every other one:
for file1 in $( ls *.bmp | head -n $(( $( ls *.bmp | wc -l) - 1)); do
for file2 in $( ls *.bmp | tail -n $(( $( ls *.bmp | wc -l) - 1)); do
    comPare file1 file2 &
    moved=$(( $(cat pipe) + 1 ))
done
done
rm pipe
echo "Moved $moved files"

到目前为止,唯一的问题是我正在使用USB驱动器工作,而权限正在阻止我创建管道。除此之外...

1

像dtmilano所说,你应该使用wait或waitpid,具体取决于你的需求。

但也许你应该将程序分成两部分,并使用exec执行子进程。当你进行fork时,你的子进程会接收到pid等于0,我不知道如果你尝试等待pid为0的进程信号是否能正常工作。

无论如何,你可以通过exit传递由子进程计算出的值,虽然这不是最好的方法。


1
如果您想保留返回值以表示成功或失败的退出状态,可以在分叉之前调用pipe(2)来设置父进程和子进程之间的单独通道。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接