child 进程向管道写入内容后无法从管道中读取
Unable to read from a pipe after something is written to it by a child process
我创建了一个函数 exec_in_child
,它将命令参数、管道文件描述符 (fds
)、read_flag
和 write_flag
作为输入。当write_flag
设置为1时,child进程应该复制stdout
到fds[1]
,然后执行命令。当 read_flag
设置为 1 时,child 应该复制 stdin
到 fds[0]
并执行命令。
- 当我 reading/writing 时,是否必须关闭管道的一端
另一端?
- 下面的代码不起作用。我正在尝试在 child 进程中执行
/bin/ls
,将标准输出写入管道,然后读取
它在 parent 过程中关闭并打印它。我无法阅读
parent 过程。
- 我可以在不关闭其他进程的情况下在同一进程内读写管道吗?当我想 child 阅读时会出现这种情况
从管道执行,然后写入管道。
#include <stdio.h> /* printf */
#include <stdlib.h>
#include <string.h> /* strlen, strcpy */
int exec_in_child(char *arguments[], const int temp[], int , int);
int main()
{
ssize_t bytes_read;
char *curr_dir = (char *)malloc(500);
int pipefd[2];
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
char *arguments[] = {"/bin/pwd",0};
exec_in_child(arguments, pipefd, 0, 1);
bytes_read = read(pipefd[0], curr_dir, strlen(curr_dir));
printf("%s = %d\n", "bytes read from pipe" ,(int)bytes_read);
printf("%s: %s\n","character read from the pipe",curr_dir);
return 0;
}
int exec_in_child(char * arguments[], const int fds[], int read_flag, int write_flag) {
pid_t pid;
pid = fork();
if (pid < 0) {
perror("Error: Fork Failed");
}
else if (pid == 0){ /*inside the child process */
if (read_flag == 1) {
dup2(fds[0], 0);
perror("Dup2 stdin");
}
if (write_flag == 1) {
dup2(fds[1], 1);
perror("Dup2 stdout");
}
execv(arguments[0], arguments);
perror("Error in child");
exit(1);
} /* if (pid == 0) */
else {
while(pid != wait(0));
} /* if(pid < 0) */
return 0;
}
我得到这个结果:
hmwk1-skk2142(test) > ./a.out
Dup2 stdout: Success
bytes read from pipe = 0
character read from the pipe:
回答您的问题:
1) 您无需关闭管道的任何一端即可使用另一端。但是,您通常希望关闭不使用的管道的任何一端。这样做的最大原因是 只有当所有打开的写入文件描述符都关闭时,管道才会关闭。
2) 您的代码无法正常工作,因为您使用 strlen()
不当。此函数通过搜索空 (0) 字符来计算字符串的长度。当您 malloc()
存储 curr_dir
时,您无法保证存储在那里的内容(尽管它通常会被清零,就像在本例中一样)。
因此,您的调用 strlen(curr_dir)
returns 零,并且 read()
系统调用认为您想要读取最多零字节的数据。将您的读取调用更改为以下内容:
bytes_read = read(pipefd[0], curr_dir, 500);
您的代码将完美运行。
3) 您可以读取和写入您拥有有效文件描述符的任何管道。单个进程绝对可以读写同一个管道
我创建了一个函数 exec_in_child
,它将命令参数、管道文件描述符 (fds
)、read_flag
和 write_flag
作为输入。当write_flag
设置为1时,child进程应该复制stdout
到fds[1]
,然后执行命令。当 read_flag
设置为 1 时,child 应该复制 stdin
到 fds[0]
并执行命令。
- 当我 reading/writing 时,是否必须关闭管道的一端 另一端?
- 下面的代码不起作用。我正在尝试在 child 进程中执行
/bin/ls
,将标准输出写入管道,然后读取 它在 parent 过程中关闭并打印它。我无法阅读 parent 过程。 - 我可以在不关闭其他进程的情况下在同一进程内读写管道吗?当我想 child 阅读时会出现这种情况 从管道执行,然后写入管道。
#include <stdio.h> /* printf */ #include <stdlib.h> #include <string.h> /* strlen, strcpy */ int exec_in_child(char *arguments[], const int temp[], int , int); int main() { ssize_t bytes_read; char *curr_dir = (char *)malloc(500); int pipefd[2]; if (pipe(pipefd) == -1) { perror("pipe"); exit(EXIT_FAILURE); } char *arguments[] = {"/bin/pwd",0}; exec_in_child(arguments, pipefd, 0, 1); bytes_read = read(pipefd[0], curr_dir, strlen(curr_dir)); printf("%s = %d\n", "bytes read from pipe" ,(int)bytes_read); printf("%s: %s\n","character read from the pipe",curr_dir); return 0; } int exec_in_child(char * arguments[], const int fds[], int read_flag, int write_flag) { pid_t pid; pid = fork(); if (pid < 0) { perror("Error: Fork Failed"); } else if (pid == 0){ /*inside the child process */ if (read_flag == 1) { dup2(fds[0], 0); perror("Dup2 stdin"); } if (write_flag == 1) { dup2(fds[1], 1); perror("Dup2 stdout"); } execv(arguments[0], arguments); perror("Error in child"); exit(1); } /* if (pid == 0) */ else { while(pid != wait(0)); } /* if(pid < 0) */ return 0; }
我得到这个结果:
hmwk1-skk2142(test) > ./a.out
Dup2 stdout: Success
bytes read from pipe = 0
character read from the pipe:
回答您的问题:
1) 您无需关闭管道的任何一端即可使用另一端。但是,您通常希望关闭不使用的管道的任何一端。这样做的最大原因是 只有当所有打开的写入文件描述符都关闭时,管道才会关闭。
2) 您的代码无法正常工作,因为您使用 strlen()
不当。此函数通过搜索空 (0) 字符来计算字符串的长度。当您 malloc()
存储 curr_dir
时,您无法保证存储在那里的内容(尽管它通常会被清零,就像在本例中一样)。
因此,您的调用 strlen(curr_dir)
returns 零,并且 read()
系统调用认为您想要读取最多零字节的数据。将您的读取调用更改为以下内容:
bytes_read = read(pipefd[0], curr_dir, 500);
您的代码将完美运行。
3) 您可以读取和写入您拥有有效文件描述符的任何管道。单个进程绝对可以读写同一个管道