使用C中的管道在父母和孩子之间发送数据

时间:2019-03-03 21:39:14

标签: c pipe

好的,所以我一直在尝试修改此代码,该代码会将数据从父进程发送到子进程,然后子进程将其平方并返回该值。 TLDR,这是使用管道的练习。我已经找到了使用两个管道来演示此功能的示例。但是我想知道是否有可能只用一根烟斗就能做到这一点。

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>

int int_pow(int base, int exp){
    int sum = base;
    for(int i = 1; i<exp; i++){
        sum = sum * base;
    }
    return sum;
}

int main(){
    int fd[2]; //0 = read, 1 = write
    pid_t pid;
    if(pipe(fd) < 0){
        printf("Error:  could not create pipe.\n");
        exit(1);
    }

    if ((pid = fork()) < 0){
        printf("Error:  could not create child.\n");
        exit(1);
    }
    printf("\n");
    //child process
    if (pid == 0){
        printf("hello from child.\n");
        int random = 0;
        int waiting = 0;
        waiting = read(fd[0], &random, sizeof(random)+1);
        printf("%d\n", random);

        random = int_pow(random,2);
        write(fd[1], &random, sizeof(random)+1);

    } else {
        printf("hello from parent.\n");
        int random = rand()%100+1;
        printf("%d\n", random);
        write(fd[1], &random, sizeof(random));
        int waiting = 0;
        waiting = read(fd[0], &random, sizeof(random)+1);
        printf("%d\n", random);
    }
    close(fd[0]); //close parent read process
    close(fd[1]); //close parent write process
    return 0;
}

更新: 我设法得到了我追求的结果。我试图使它变得比所需的复杂得多。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <time.h>

int int_pow(int n, int exp){
    int sum = n;
    for (int i = 1; i < exp; i++){
        sum = sum * n;
    }
    return sum;
}

int main()
{
    int random = 0;
    pid_t fpid;
    int p[2]; // 0 = read, 1 = write

    if (pipe(p) < 0){
        exit(1);
    }

    fpid = fork();

    if (fpid == 0){

        printf("\n(Child) Hello from child. \n");
        read(p[0], &random, sizeof(random));
        printf("(Child) Recieved from parent: %d \n", random);
        random = int_pow(random, 2);
        printf("(Child) Sent from child: %d \n", random);
        write(p[1], &random, sizeof(random));

        close(p[0]);//close child read.
        close(p[1]);//close child write.

        exit(0);
    } else {
        //wait(NULL);
        printf("(Parent) Hello from parent. \n");

        random = rand()%100+1;
        printf("(Parent) Sent from parent: %d \n", random);
        write(p[1], &random, sizeof(random));
        sleep(1);
        int wait = read(p[0], &random, sizeof(random));

        close(p[0]);//close parent read.
        close(p[1]);//close parent write.


        printf("(Parent) Recieved from Child: %d \n", random);
        exit(0);
    }
    return 0;
}

3 个答案:

答案 0 :(得分:1)

我能够弄清楚该怎么做。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <time.h>

int int_pow(int n, int exp){
    int sum = n;
    for (int i = 1; i < exp; i++){
        sum = sum * n;
    }
    return sum;
}

int main()
{
    int random = 0;
    pid_t fpid;
    int p[2]; // 0 = read, 1 = write

    if (pipe(p) < 0){
        exit(1);
    }

    fpid = fork();

    if (fpid == 0){

        printf("\n(Child) Hello from child. \n");
        read(p[0], &random, sizeof(random));
        printf("(Child) Recieved from parent: %d \n", random);
        random = int_pow(random, 2);
        printf("(Child) Sent from child: %d \n", random);
        write(p[1], &random, sizeof(random));

        close(p[0]);//close child read.
        close(p[1]);//close child write.

        exit(0);
    } else {
        //wait(NULL);
        printf("(Parent) Hello from parent. \n");

        random = rand()%100+1;
        printf("(Parent) Sent from parent: %d \n", random);
        write(p[1], &random, sizeof(random));
        sleep(1);
        int wait = read(p[0], &random, sizeof(random));

        close(p[0]);//close parent read.
        close(p[1]);//close parent write.


        printf("(Parent) Recieved from Child: %d \n", random);
        exit(0);
    }
    return 0;
}

答案 1 :(得分:0)

否;您的代码将无法正常工作,因为父进程可以使用他编写的数据。

例如

parent              child
--------------------------
write()
read()
                    read() --> blocks

例如,可以通过在孩子sleep(5)之前放置read()来模拟此情况。

您将需要其他同步方式;例如kill(getpid(), SIGSTOP)之后的父级write()kill(getppid(), SIGCONT)之后的子级read()

答案 2 :(得分:0)

如果您使用的是Linux操作系统,只需键入

man 2 pipe

您将有一个与代码非常相似的工作示例。或点击此链接http://man7.org/linux/man-pages/man2/pipe.2.html

通过比较它们,您可以找到自己有误解的地方。

管道只能读取一次,将其视为水管,不像常规文件,尽管也使用文件描述符。例如,在水管中,您在一端装入1升水,而在另一端只能取出1升。正如许多评论所说,读入的父母消耗了1升水,因此孩子的过程永远没有机会得到它们。