2管,一个叉,bc和execlp(C)

时间:2017-12-09 14:41:49

标签: c pipe fork

我正在尝试使用管道和叉子在c中使用这样的东西: 回声“像10 + 10的操作”| BC

确切地说,我试图创建2个管道,一个用于服务器将写入操作并且bc将读取,另一个用于操作的结果(通过bc),服务器将读取并打印它。为此,我正在更改父进程和子进程的输出和输入。

这是我的代码:

int main(){

int t1, t2;
char resultat[5];
int pipe1[2];
int pipe2[2];

pipe(pipe1);
pipe(pipe2);


int resultat_fork = fork();

if(resultat_fork == -1){
    exit(EXIT_FAILURE);
}

if(resultat_fork!=0){  
    printf("I am the parent\n");

    close(pipe1[0]);
    close(pipe2[1]);
    //We only want to write into pipe1 and read from pipe2, we can close the two other

    write(pipe1[1], "20*5\n", 20);
    //write on pipe1 the expression

    read(pipe2[0], resultat, sizeof(resultat));
    //read from pipe2 the answer (written by bc)

    printf("resultat : %s\n",resultat);

    close(pipe1[1]);
    close(pipe2[0]);


}else{  
    printf("I am the children\n");

    close(pipe1[1]);
    close(pipe2[0]);
    //We only want to write into pipe2 and read from pipe1, we can close the two other

    dup2(pipe1[0], 0);  
    //redirection standard input to pipe1[0]

    dup2(pipe2[1], 1);
    //redirection standard output to pipe2[1]

    execlp("bc", "bc", NULL);
    //execute bc, which normaly will read the operation from pipe1 and write the answer into pipe2, but I think it's here the problem come out

    close(pipe1[0]);
    close(pipe2[1]);
}


return 0;

}

我得到了正确答案,但错误: “(standard_in)2:非法字符:^ @” “(standard_in)2:非法字符:” 加上我必须按CTRL C退出。 我猜它来自BC,但为什么......

我做错了什么?谢谢! 我已经看过很少例,但只扔了一根烟斗。

1 个答案:

答案 0 :(得分:1)

这很有效。请注意它如何指定要写入的数据的大小,以及它如何检查写入和读取,以及它如何关闭文件描述符。 (请记住:sizeof("string literal")计算空字节,与strlen()不同。它也是编译时常量。但是,更通用的代码会在当前表达式字符串上使用strlen()。)

经验法则:如果您使用dup2()将管道文件描述符复制到标准输入或标准输出,请关闭 两者 管道末端。

如果您使用dup()fcntl()代替F_DUPFDF_DUPFD_CLOEXEC,这也适用。

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

int main(void)
{
    char resultat[5];
    int pipe1[2];
    int pipe2[2];

    pipe(pipe1);
    pipe(pipe2);

    int resultat_fork = fork();

    if (resultat_fork == -1)
    {
        exit(EXIT_FAILURE);
    }

    if (resultat_fork != 0)
    {
        printf("I am the parent\n");

        close(pipe1[0]);
        close(pipe2[1]);

        if (write(pipe1[1], "20*5\n", sizeof("20*5\n") - 1) != sizeof("20*5\n") - 1)
            fprintf(stderr, "write to child failed\n");

        int nbytes = read(pipe2[0], resultat, sizeof(resultat));
        if (nbytes <= 0)
            fprintf(stderr, "read from child failed\n");
        else
            printf("resultat: [%.*s]\n", nbytes, resultat);

        close(pipe1[1]);
        close(pipe2[0]);
    }
    else
    {
        printf("I am the child\n");

        close(pipe1[1]);
        close(pipe2[0]);
        dup2(pipe1[0], 0);
        dup2(pipe2[1], 1);
        close(pipe1[0]);    /* More closes! */
        close(pipe2[1]);    /* More closes! */

        execlp("bc", "bc", NULL);
        fprintf(stderr, "Failed to execute bc\n");
        exit(EXIT_FAILURE);
    }

    return 0;
}

仍然有改进错误处理的空间;在报告了一些错误后,代码会继续播放,这可能不是最好的行为。

输出:

I am the parent
I am the child
resultat: [100
]

(注意:如果您将程序的输出传送到某处,则看不到I am the child消息。出于原因,请参阅printf() anomaly after fork()。)