C Linux系统使用Fork()将int传递给子进程和父进程来调用问题

C Linux系统使用Fork()将int传递给子进程和父进程来调用问题,c,linux,fork,C,Linux,Fork,我正在开发一个程序,它将接受一个整数并创建两个进程,一个父进程和一个子进程。父级将从整数中减去5,传递给将其除以5的子级,然后他们将重复此过程5次,每次打印整数的当前值 整数可以通过文本文件传递,既可以写入也可以读取,或者可以使用更简单的管道 我一直在查找所需的系统调用,并且有一个半工作程序。然而,我已经被困了几个小时,我想我的问题是我不能让他们等待对方完成,因为我的输出不正确 这是我到目前为止得到的 #include <stdio.h> #include <unistd.h&

我正在开发一个程序,它将接受一个整数并创建两个进程,一个父进程和一个子进程。父级将从整数中减去5,传递给将其除以5的子级,然后他们将重复此过程5次,每次打印整数的当前值

整数可以通过文本文件传递,既可以写入也可以读取,或者可以使用更简单的管道

我一直在查找所需的系统调用,并且有一个半工作程序。然而,我已经被困了几个小时,我想我的问题是我不能让他们等待对方完成,因为我的输出不正确

这是我到目前为止得到的

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <ctype.h>
#include <fcntl.h>

int main(void)
{    
    int x=19530;
    int w=1;
    int fd[2];
    pipe(fd);
    int pid = fork();

    int k;
    for (k=0; k<5; k++) {
        if (pid>0) {
            //int x = 19530;

            if ((close(fd[0]))==-1) {
                perror("Close:");
            }

            read(fd[0], &x, sizeof(int));
            x=x-5;
            write (fd[1], &x, sizeof(int));
            printf("X in parent %d\n", x);

            close(fd[1]);
            close(fd[0]);
        } else if (pid==0) {

            if ((close(fd[1]))==-1) {
                perror("Close:");
            }

            read(fd[0], &x, sizeof(int));
            x=x/5;
            printf("X in child %d\n", x);
            write (fd[1], &x, sizeof(int));

            close(fd[1]);
            close(fd[0]);
        }
    }
    return 0;
}
一开始似乎不错,但是孩子没有正确地返回,然后家长在孩子赶上之前连续跑了太多次。我还试图修复那个坏的文件描述符,但没有用

任何帮助都将不胜感激

谢谢。

\include
#include <stdio.h>
#include <unistd.h>
#include <err.h>

#define ok(x) ({ int i_ = (x); if (i_ == -1) err(1, #x); i_; })

enum { p_, c_ }; // parent, child
enum { r_, w_ }; // read, write

int main(void)
{
        int x = 19530;
        int fd[2][2];
        int pid;

        ok(pipe(fd[0]));
        ok(pipe(fd[1]));

        ok(pid = fork());

        close(fd[p_][pid ? r_ : w_]);
        close(fd[c_][pid ? w_ : r_]);

        for (int i = 0; i < 5; i++) {
                if (pid) {
                        x -= 5;
                        printf("X in parent %d\n", x);
                        ok(write(fd[p_][w_], &x, sizeof(x)));
                        ok(read(fd[c_][r_], &x, sizeof(x)));
                }
                else {
                        ok(read(fd[p_][r_], &x, sizeof(x)));
                        x /= 5;
                        printf("X in child %d\n", x);
                        ok(write(fd[c_][w_], &x, sizeof(x)));
                }
        }
        return 0;
}
#包括 #包括 #定义ok(x)({int i_=(x);if(i_==-1)err(1,#x);i_=}) 枚举{p_u,c_u};//父母、孩子 枚举{r_u,w_u};//读,写 内部主(空) { int x=19530; int fd[2][2]; int-pid; ok(管道(fd[0]); ok(管道(fd[1]); ok(pid=fork()); 关闭(fd[p_][pid?r_:w_]); 关闭(fd[c_uu][pid?w_uu:r_u]); 对于(int i=0;i<5;i++){ 如果(pid){ x-=5; printf(“父%d中的X\n”,X); ok(写入(fd[p_u][w_u],&x,sizeof(x)); 好(读(fd[c_][r_],&x,sizeof(x)); } 否则{ 好(读(fd[p_][r_],&x,sizeof(x)); x/=5; printf(“子%d中的X\n”,X); ok(写入(fd[c_u][w_u],&x,sizeof(x)); } } 返回0; }
管道是单向的,所以需要两个。我使用了一些枚举,试图使内容更易于阅读。

\include
#包括
#包括
#定义ok(x)({int i_=(x);if(i_==-1)err(1,#x);i_=})
枚举{p_u,c_u};//父母、孩子
枚举{r_u,w_u};//读,写
内部主(空)
{
int x=19530;
int fd[2][2];
int-pid;
ok(管道(fd[0]);
ok(管道(fd[1]);
ok(pid=fork());
关闭(fd[p_][pid?r_:w_]);
关闭(fd[c_uu][pid?w_uu:r_u]);
对于(int i=0;i<5;i++){
如果(pid){
x-=5;
printf(“父%d中的X\n”,X);
ok(写入(fd[p_u][w_u],&x,sizeof(x));
好(读(fd[c_][r_],&x,sizeof(x));
}
否则{
好(读(fd[p_][r_],&x,sizeof(x));
x/=5;
printf(“子%d中的X\n”,X);
ok(写入(fd[c_u][w_u],&x,sizeof(x));
}
}
返回0;
}

管道是单向的,所以需要两个。我使用了一些枚举来尝试使内容更易于阅读。

关闭文件描述符后,您既不能读取也不能写入文件描述符。您可以创建一对文件描述符。然后,你关闭它们5次。在你第一次关闭它之后,它就关闭了。你期望发生什么?你让每一方先进行
读取
,然后进行
写入
read
将被阻止,直到有人调用
write
,所以谁先写?@immibis,
fork()
在循环之外。循环循环时,子进程不会分叉。此外,过早关闭管道末端的问题,使进程彼此等待确实存在问题。管道可以帮助实现这一点,因为从管道中读取数据会阻塞可用的数据,但这并不适用于您,因为每个进程都可以从管道中读回它刚刚编写的任何内容。一个通常会建立两个管道,每个管道单向使用。关闭文件描述符后,您既不能读取也不能写入文件描述符。您可以创建一对文件描述符。然后,你关闭它们5次。在你第一次关闭它之后,它就关闭了。你期望发生什么?你让每一方先进行
读取
,然后进行
写入
read
将被阻止,直到有人调用
write
,所以谁先写?@immibis,
fork()
在循环之外。循环循环时,子进程不会分叉。此外,过早关闭管道末端的问题,使进程彼此等待确实存在问题。管道可以帮助实现这一点,因为从管道中读取数据会阻塞可用的数据,但这并不适用于您,因为每个进程都可以从管道中读回它刚刚编写的任何内容。通常会建立两个管道,每个管道单向使用。使用
很有趣;它在BSD(包括Mac OS X)和Linux上可用,但不一定在其他任何地方。OTOH,这与我在过去25年左右使用的一套错误报告例程非常相似。就我个人而言,我觉得单字母、尾随下划线的名称会让人分心。如果有人需要,CCAN有一个err.h的开源实现:。语句表达式受gcc、clang甚至icc的支持,所以我感觉很好。:)您正在使用GCC扩展()而没有调用它。使用
很有趣;它在BSD(包括Mac OS X)和Linux上可用,但不一定在其他任何地方。OTOH,这与我在过去25年左右使用的一套错误报告例程非常相似。就我个人而言,我发现只有一个字母,尾随下划线n
#include <stdio.h>
#include <unistd.h>
#include <err.h>

#define ok(x) ({ int i_ = (x); if (i_ == -1) err(1, #x); i_; })

enum { p_, c_ }; // parent, child
enum { r_, w_ }; // read, write

int main(void)
{
        int x = 19530;
        int fd[2][2];
        int pid;

        ok(pipe(fd[0]));
        ok(pipe(fd[1]));

        ok(pid = fork());

        close(fd[p_][pid ? r_ : w_]);
        close(fd[c_][pid ? w_ : r_]);

        for (int i = 0; i < 5; i++) {
                if (pid) {
                        x -= 5;
                        printf("X in parent %d\n", x);
                        ok(write(fd[p_][w_], &x, sizeof(x)));
                        ok(read(fd[c_][r_], &x, sizeof(x)));
                }
                else {
                        ok(read(fd[p_][r_], &x, sizeof(x)));
                        x /= 5;
                        printf("X in child %d\n", x);
                        ok(write(fd[c_][w_], &x, sizeof(x)));
                }
        }
        return 0;
}