2016-12-06 95 views
1

我在C练习中遇到了一个问题。 任务是创建两个进程。这两个连接两个管道,终止于孩子的stdin和stdout。子进程然后用bc替换。 然后我应该写一个从父项到子进程(bc)的术语(例如1 + 2)。通过C中的管道向bc写入一个术语

管道正在做他们应该做的事情,但是,bc似乎并不喜欢输入。当我写入管,BC与下面的多行回应:

(standard_in) 1: illegal character: ^@ 

这是我的解决方案迄今:

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

int main(int argc, char *argv[]) { 

    /*Create two pipes: 
     One from parent to child (pipe_pc) 
     and one from child to parent (pipe_cp). 
    */ 
    int pipe_pc[2], pipe_cp[2]; 

    int cid; 

    if (pipe(pipe_pc) == -1 || pipe(pipe_cp) == -1) { 
     printf("Could not pipe\n"); 
     exit(EXIT_FAILURE); 
    } 

    // Create child process 
    cid = fork(); 

    if (cid == -1) { 
     printf("Could not fork.\n"); 
     exit(EXIT_FAILURE); 
    } 

    // Child process 
    if (cid == 0) { 

     // Redirect pipes 
     close(STDOUT_FILENO); 
     close(STDIN_FILENO); 
     close(pipe_pc[1]); // Close writing end 
     close(pipe_cp[0]); // Close reading end 

     dup2(pipe_pc[0], STDIN_FILENO); // Take stdin from parent 
     dup2(pipe_cp[1], STDOUT_FILENO); // Give stdout to parent 

     int err; 

     // Replace child with bc 
     err = execl("/usr/bin/bc", "bc --quiet", (char*) NULL); 

     printf("%s %d\n", "Could not start bc:", err); 
     exit(err); 
    } 

    // Parent Process 
    else { 

     char input[128] = ""; 
     char buffer[128] = ""; 

     printf("%s\n", "Parent process running"); 

     // Copy argv to a single string 
     for(int i=1; i < argc; i++) { 
      strcat(input, argv[i]); 
     } 

     // Write the input to the child's stdin 
     write(pipe_pc[1], input, sizeof(input); 

     // Read the child's stdout 
     read(pipe_cp[0], buffer, sizeof(buffer)); 

     printf("Result: %s\n", buffer); 

     return 0; 
    } 

} 

提示和帮助非常感谢,谢谢提前!

回答

0

问题是你没有在管道中正确写入,所以bc收到错误的输入。

我重写了else分支。

如果您不确定您在管道中发送了什么,请用0(I/O fd)暂时替换管道描述符,然后直观检查您做了什么。

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

int main(int argc, char *argv[]) { 

    /* Create two pipes: One from parent to child (pipe_pc) and one 
     from child to parent (pipe_cp). 
    */ 
    int pipe_pc[2], pipe_cp[2]; 

    int cid; 

    if (pipe(pipe_pc) == -1 || pipe(pipe_cp) == -1) { 
     printf("Could not pipe\n"); 
     exit(EXIT_FAILURE); 
    } 

    // Create child process 
    cid = fork(); 

    if (cid == -1) { 
     printf("Could not fork.\n"); 
     exit(EXIT_FAILURE); 
    } 

    // Child process 
    if (cid == 0) { 

     // Redirect pipes 
     close(STDOUT_FILENO); 
     close(STDIN_FILENO); 
     close(pipe_pc[1]); // Close writing end 
     close(pipe_cp[0]); // Close reading end 

     dup2(pipe_pc[0], STDIN_FILENO); // Take stdin from parent 
     dup2(pipe_cp[1], STDOUT_FILENO); // Give stdout to parent 

     int err; 

     // Replace child with bc 
     err = execl("/usr/bin/bc", "bc --quiet", (char*) NULL); 

     printf("%s %d\n", "Could not start bc:", err); 
     exit(err); 
    } 

    // Parent Process 
    else { 
     char buffer[128] = ""; 

     // printf("%s\n", "Parent process running"); 

     for(int i=1; i < argc; i++) 
      write(pipe_pc[1], argv[i], strlen(argv[i])); 

     write(pipe_pc[1], "\n", 1); 

     read(pipe_cp[0], buffer, sizeof(buffer)); 

     printf("Result: %s\n", buffer); 

     return 0; 
    } 

} 
0

你的代码有很多未定义的行为。


write(pipe_pc[1], input, sizeof(input); 

你写的所有输入数组。但是您只需要将您复制的内容写入strcat()即可。 使用strlen。

write(pipe_pc[1], input, strlen(input)); 

strcat(input, argv[i]); 

在这里,你应该确认您不超过128字节的。

if (strlen(input) + strlen(argv[i]) + 1 > 128) { 
    break; 
} 
strcat(input, argv[i]); 

read(pipe_cp[0], buffer, sizeof(buffer)); 

这里你不验证缓冲区是一个有效的C字符串。

ssize_t ret = read(pipe_cp[0], buffer, sizeof(buffer) - 1); 
if (ret < 0) 
    return 1; 
buffer[ret] = '\0'; 

你忘了父

close(pipe_pc[0]); 
close(pipe_cp[1]); 

和你读后关闭管道/写

close(pipe_pc[1]); 
close(pipe_cp[0]); 

你忘了关闭后管在孩子的dup2()

close(pipe_pc[1]); 
close(pipe_cp[0]); 

您不需要在dup2之前关闭旧的fd,他会为您做。而你不检查错误的dup2()