通过 C 中的管道向 bc 写入一个术语
Writing a term to bc via pipes in C
我 运行 遇到了这个 C 练习题。
任务是创建两个进程。两者通过终止于 child 的 stdin 和 stdout 的两个管道相连。然后 child 进程被 bc 替换。
然后我应该写一个术语(例如 1 + 2)从 parent 到 child 过程(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;
}
}
非常感谢提示和帮助,提前致谢!
您的代码有很多未定义的行为。
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));
这里你没有验证 buffer 是一个有效的 c 字符串。
ssize_t ret = read(pipe_cp[0], buffer, sizeof(buffer) - 1);
if (ret < 0)
return 1;
buffer[ret] = '[=15=]';
您忘记关闭父级中的管道
close(pipe_pc[0]);
close(pipe_cp[1]);
在你的 read/write
之后
close(pipe_pc[1]);
close(pipe_cp[0]);
您忘记在 dup2()
后关闭子管道
close(pipe_pc[1]);
close(pipe_cp[0]);
你不需要在 dup2 之前关闭你的旧 fd,他会为你做。而且您不检查 dup2()
的错误
问题是你没有在管道中正确写入,所以 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;
}
}
我 运行 遇到了这个 C 练习题。 任务是创建两个进程。两者通过终止于 child 的 stdin 和 stdout 的两个管道相连。然后 child 进程被 bc 替换。 然后我应该写一个术语(例如 1 + 2)从 parent 到 child 过程(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;
}
}
非常感谢提示和帮助,提前致谢!
您的代码有很多未定义的行为。
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));
这里你没有验证 buffer 是一个有效的 c 字符串。
ssize_t ret = read(pipe_cp[0], buffer, sizeof(buffer) - 1);
if (ret < 0)
return 1;
buffer[ret] = '[=15=]';
您忘记关闭父级中的管道
close(pipe_pc[0]);
close(pipe_cp[1]);
在你的 read/write
之后close(pipe_pc[1]);
close(pipe_cp[0]);
您忘记在 dup2()
close(pipe_pc[1]);
close(pipe_cp[0]);
你不需要在 dup2 之前关闭你的旧 fd,他会为你做。而且您不检查 dup2()
问题是你没有在管道中正确写入,所以 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;
}
}