当它被重定向到另一个进程时,将“\n”添加到 stdout 的重要性是什么?
What is the importance of adding "\n" to stdout when it's redirected to another process?
所以,我在用 c 语言玩管道,我有一个练习,我通过命令行调用一个程序,如下所示:“./self 1”,然后使用 execlp 调用自身,但参数为 2: “./self 2”进一步用参数 3 调用自身:“./self 3”。这些进程的重点是:process1 从键盘获取一行并将其放入 pipe1,然后 process2 从 pipe1 获取该行并将其放入 pipe2,然后 process3 从 pipe2 获取它并计算 space 个字符.如果我在使用 fprintf(stdout,"\n") 进行输入之前不在屏幕上打印换行符,则此代码永远不会工作; .这是为什么?
代码如下:
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
if (strcmp(argv[1], "1") == 0) {
int fdpipe1[2];
if (pipe(fdpipe1)) {
printf("Error pipe1\n");
return 0;
}
pid_t p;
p = fork();
if (p == 0) {
close(fdpipe1[1]);
dup2(fdpipe1[0], 0);
execlp("./self", "./self", "2", NULL);
} else {
close(fdpipe1[0]);
fprintf(stdout, "\n");
dup2(fdpipe1[1], 1);
char input[100];
gets(input);
puts(input);
wait(NULL);
}
}
else if (strcmp(argv[1], "2") == 0) {
int fdpipe2[2];
if (pipe(fdpipe2)) {
printf("Error pipe2\n");
return 0;
}
pid_t p;
p = fork();
if (p == 0) {
close(fdpipe2[1]);
dup2(fdpipe2[0], 0);
execlp("./self", "./self", "3", NULL);
} else {
close(fdpipe2[0]);
fprintf(stdout, "\n");
dup2(fdpipe2[1], 1);
char input[100];
gets(input);
puts(input);
wait(NULL);
}
}
else if (strcmp(argv[1], "3") == 0) {
char input[100];
gets(input);
int i = 0, counter = 0;
while (input[i] != '[=10=]') {
if (input[i++] == ' ') counter++;
}
printf("%d\n", counter);
}
return;
}
在这种构造中,当您通过未命名管道将进程的 stdout
连接到另一个进程的 stdin
时,通常会添加换行符以确保发送流,即 stdout
缓冲区被刷新,作为并行示例,当您使用 scanf
时,仅当您按下回车时(换行符添加到 stdin
)是读取的流,这里也适用类似的原理。
我建议您使用 STDIN_FILENO
和 STDOUT_FILENO
内置宏而不是硬编码的文件描述符,如果不是为了别的,它使代码对于不熟悉此事的人更具可读性。
请避免使用gets
,这是一个危险的函数,它不检查目标缓冲区的边界,它会导致各种麻烦,以至于它被弃用了,后来被从标准,虽然它仍然可以与某些编译器一起使用,但出于我想象的遗留原因,请在 post 上查看关于此主题的精彩答案:
Why is the gets function so dangerous that it should not be used?
建议改用 fgets
。
所以,我在用 c 语言玩管道,我有一个练习,我通过命令行调用一个程序,如下所示:“./self 1”,然后使用 execlp 调用自身,但参数为 2: “./self 2”进一步用参数 3 调用自身:“./self 3”。这些进程的重点是:process1 从键盘获取一行并将其放入 pipe1,然后 process2 从 pipe1 获取该行并将其放入 pipe2,然后 process3 从 pipe2 获取它并计算 space 个字符.如果我在使用 fprintf(stdout,"\n") 进行输入之前不在屏幕上打印换行符,则此代码永远不会工作; .这是为什么?
代码如下:
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
if (strcmp(argv[1], "1") == 0) {
int fdpipe1[2];
if (pipe(fdpipe1)) {
printf("Error pipe1\n");
return 0;
}
pid_t p;
p = fork();
if (p == 0) {
close(fdpipe1[1]);
dup2(fdpipe1[0], 0);
execlp("./self", "./self", "2", NULL);
} else {
close(fdpipe1[0]);
fprintf(stdout, "\n");
dup2(fdpipe1[1], 1);
char input[100];
gets(input);
puts(input);
wait(NULL);
}
}
else if (strcmp(argv[1], "2") == 0) {
int fdpipe2[2];
if (pipe(fdpipe2)) {
printf("Error pipe2\n");
return 0;
}
pid_t p;
p = fork();
if (p == 0) {
close(fdpipe2[1]);
dup2(fdpipe2[0], 0);
execlp("./self", "./self", "3", NULL);
} else {
close(fdpipe2[0]);
fprintf(stdout, "\n");
dup2(fdpipe2[1], 1);
char input[100];
gets(input);
puts(input);
wait(NULL);
}
}
else if (strcmp(argv[1], "3") == 0) {
char input[100];
gets(input);
int i = 0, counter = 0;
while (input[i] != '[=10=]') {
if (input[i++] == ' ') counter++;
}
printf("%d\n", counter);
}
return;
}
在这种构造中,当您通过未命名管道将进程的 stdout
连接到另一个进程的 stdin
时,通常会添加换行符以确保发送流,即 stdout
缓冲区被刷新,作为并行示例,当您使用 scanf
时,仅当您按下回车时(换行符添加到 stdin
)是读取的流,这里也适用类似的原理。
我建议您使用 STDIN_FILENO
和 STDOUT_FILENO
内置宏而不是硬编码的文件描述符,如果不是为了别的,它使代码对于不熟悉此事的人更具可读性。
请避免使用gets
,这是一个危险的函数,它不检查目标缓冲区的边界,它会导致各种麻烦,以至于它被弃用了,后来被从标准,虽然它仍然可以与某些编译器一起使用,但出于我想象的遗留原因,请在 post 上查看关于此主题的精彩答案:
Why is the gets function so dangerous that it should not be used?
建议改用 fgets
。