从管道读取数据时的奇怪行为
Strange behavior when reading data from pipe
仔细阅读手册后(即man 2 pipe
),我找到了一个演示代码片段:
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int
main(int argc, char *argv[])
{
int pipefd[2];
pid_t cpid;
char buf;
if (argc != 2) {
fprintf(stderr, "Usage: %s <string>\n", argv[0]);
exit(EXIT_FAILURE);
}
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { /* Child reads from pipe */
close(pipefd[1]); /* Close unused write end */
while (read(pipefd[0], &buf, 1) > 0)
write(STDOUT_FILENO, &buf, 1);
write(STDOUT_FILENO, "\n", 1);
close(pipefd[0]);
_exit(EXIT_SUCCESS);
} else { /* Parent writes argv[1] to pipe */
close(pipefd[0]); /* Close unused read end */
write(pipefd[1], argv[1], strlen(argv[1]));
close(pipefd[1]); /* Reader will see EOF */
wait(NULL); /* Wait for child */
exit(EXIT_SUCCESS);
}
}
我对上面的代码片段做了一些小修改(即:在父进程中添加 sleep
并在子进程中打印出 read
返回的大小)。
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <string>
#include <thread>
#include <array>
#include <iostream>
int
main(int argc, char *argv[])
{
int pipefd[2];
pid_t cpid;
std::array<char, 1024> buf;
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { /* Child reads from pipe */
close(pipefd[1]); /* Close unused write end */
int size;
while (size = read(pipefd[0], buf.data(), 1) > 0)
std::cout << size << std::endl;
write(STDOUT_FILENO, "\n", 1);
close(pipefd[0]);
_exit(EXIT_SUCCESS);
} else { /* Parent writes argv[1] to pipe */
close(pipefd[0]); /* Close unused read end */
std::string str{"hello world\n"};
write(pipefd[1], str.c_str(), str.size());
std::this_thread::sleep_for(std::chrono::seconds(5));
close(pipefd[1]); /* Reader will see EOF */
wait(NULL); /* Wait for child */
exit(EXIT_SUCCESS);
}
}
以上代码片段的输出如下:
1
1
1
1
1
1
1
1
1
1
1
1
目前看来还不错。令人困惑的是,当我将字节数增加到 read.The 时,输出非常 strange.Here 就是所说的 code snippet:
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <string>
#include <thread>
#include <array>
#include <iostream>
int
main(int argc, char *argv[])
{
int pipefd[2];
pid_t cpid;
std::array<char, 1024> buf;
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { /* Child reads from pipe */
close(pipefd[1]); /* Close unused write end */
int size;
while (size = read(pipefd[0], buf.data(), buf.size()) > 0)
std::cout << size << std::endl;
write(STDOUT_FILENO, "\n", 1);
close(pipefd[0]);
_exit(EXIT_SUCCESS);
} else { /* Parent writes argv[1] to pipe */
close(pipefd[0]); /* Close unused read end */
std::string str{"hello world\n"};
write(pipefd[1], str.c_str(), str.size());
std::this_thread::sleep_for(std::chrono::seconds(5));
close(pipefd[1]); /* Reader will see EOF */
wait(NULL); /* Wait for child */
exit(EXIT_SUCCESS);
}
}
这是奇怪的输出:
1
//new line, and no more output indeed.
也许我需要知道 pipe
use.And 返回的文件描述符的缓冲类型我在手册中找不到任何有用的信息(即 man 2 pipe
)。
有人能解释一下这件事吗?
>
的 operator precedence 高于 =
。因此,
size = read(pipefd[0], buf.data(), buf.size()) > 0
等同于
size = (read(pipefd[0], buf.data(), buf.size()) > 0)
第一次迭代似乎会消耗所有数据,因此 read
应该 return 12
。 12 > 0
是 true
,true
隐式转换为整数值 1
。
下一次迭代,read
应该return一个non-positive数字,结束循环。
当 read
大小为 1
时,其预期 return 值与 1 > 0
.
的结果没有区别
在赋值前后加上括号。
(size = read(pipefd[0], buf.data(), buf.size())) > 0
仔细阅读手册后(即man 2 pipe
),我找到了一个演示代码片段:
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int
main(int argc, char *argv[])
{
int pipefd[2];
pid_t cpid;
char buf;
if (argc != 2) {
fprintf(stderr, "Usage: %s <string>\n", argv[0]);
exit(EXIT_FAILURE);
}
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { /* Child reads from pipe */
close(pipefd[1]); /* Close unused write end */
while (read(pipefd[0], &buf, 1) > 0)
write(STDOUT_FILENO, &buf, 1);
write(STDOUT_FILENO, "\n", 1);
close(pipefd[0]);
_exit(EXIT_SUCCESS);
} else { /* Parent writes argv[1] to pipe */
close(pipefd[0]); /* Close unused read end */
write(pipefd[1], argv[1], strlen(argv[1]));
close(pipefd[1]); /* Reader will see EOF */
wait(NULL); /* Wait for child */
exit(EXIT_SUCCESS);
}
}
我对上面的代码片段做了一些小修改(即:在父进程中添加 sleep
并在子进程中打印出 read
返回的大小)。
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <string>
#include <thread>
#include <array>
#include <iostream>
int
main(int argc, char *argv[])
{
int pipefd[2];
pid_t cpid;
std::array<char, 1024> buf;
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { /* Child reads from pipe */
close(pipefd[1]); /* Close unused write end */
int size;
while (size = read(pipefd[0], buf.data(), 1) > 0)
std::cout << size << std::endl;
write(STDOUT_FILENO, "\n", 1);
close(pipefd[0]);
_exit(EXIT_SUCCESS);
} else { /* Parent writes argv[1] to pipe */
close(pipefd[0]); /* Close unused read end */
std::string str{"hello world\n"};
write(pipefd[1], str.c_str(), str.size());
std::this_thread::sleep_for(std::chrono::seconds(5));
close(pipefd[1]); /* Reader will see EOF */
wait(NULL); /* Wait for child */
exit(EXIT_SUCCESS);
}
}
以上代码片段的输出如下:
1
1
1
1
1
1
1
1
1
1
1
1
目前看来还不错。令人困惑的是,当我将字节数增加到 read.The 时,输出非常 strange.Here 就是所说的 code snippet:
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <string>
#include <thread>
#include <array>
#include <iostream>
int
main(int argc, char *argv[])
{
int pipefd[2];
pid_t cpid;
std::array<char, 1024> buf;
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { /* Child reads from pipe */
close(pipefd[1]); /* Close unused write end */
int size;
while (size = read(pipefd[0], buf.data(), buf.size()) > 0)
std::cout << size << std::endl;
write(STDOUT_FILENO, "\n", 1);
close(pipefd[0]);
_exit(EXIT_SUCCESS);
} else { /* Parent writes argv[1] to pipe */
close(pipefd[0]); /* Close unused read end */
std::string str{"hello world\n"};
write(pipefd[1], str.c_str(), str.size());
std::this_thread::sleep_for(std::chrono::seconds(5));
close(pipefd[1]); /* Reader will see EOF */
wait(NULL); /* Wait for child */
exit(EXIT_SUCCESS);
}
}
这是奇怪的输出:
1
//new line, and no more output indeed.
也许我需要知道 pipe
use.And 返回的文件描述符的缓冲类型我在手册中找不到任何有用的信息(即 man 2 pipe
)。
有人能解释一下这件事吗?
>
的 operator precedence 高于 =
。因此,
size = read(pipefd[0], buf.data(), buf.size()) > 0
等同于
size = (read(pipefd[0], buf.data(), buf.size()) > 0)
第一次迭代似乎会消耗所有数据,因此 read
应该 return 12
。 12 > 0
是 true
,true
隐式转换为整数值 1
。
下一次迭代,read
应该return一个non-positive数字,结束循环。
当 read
大小为 1
时,其预期 return 值与 1 > 0
.
在赋值前后加上括号。
(size = read(pipefd[0], buf.data(), buf.size())) > 0