使用管道在两个进程之间连续传递数据
Using pipe to pass data between two processes continuously
我正在尝试让两个 child 进程通过管道相互通信。
一个 child 应该继续从 stdin 读取,将读取的内容传递给管道,而另一个 child 应该从管道读取并将其打印到 stdout。
我设法让它工作,但只有一次,在读取数字后的第二次迭代中,我得到:write failed: Bad file descriptor
。
我不知道我做错了什么...
#define READ 0
#define WRITE 1
int main(){
int pipe_descs[2];
int retval = pipe(pipe_descs);
int pid = fork();
if(pid == 0){ //son that reads from stdin and writes to pipe
close(pipe_descs[READ]);
int x;
while(1){
open(pipe_descs[WRITE]);
scanf("%d", &x);
if(write(pipe_descs[WRITE], &x, sizeof(int)) != sizeof(int)){
perror("write failed");
exit(EXIT_FAILURE);
}
close(pipe_descs[WRITE]);
}
perror("");
}
else if(pid > 0){ //parent
int pid = fork();
if(pid == 0){ //son that reads from pipe and write to stdout
int pipestat;
int readNum;
close(pipe_descs[WRITE]);
while((pipestat = read(pipe_descs[READ], &readNum, sizeof(int))) > 0){
printf("read: %d \n", readNum);
//close(pipe_descs[READ]);
//open(pipe_descs[READ]);
}
if (pipestat==-1) {
perror("");
fprintf(stderr, "error to pipe... exiting\n");
exit(EXIT_FAILURE);
}
}
}
int status;
int i = 2;
while (i > 0){
wait(&status);
i--;
}
}
问题 #1
如果您要关闭编写器(close(pipe_descs[WRITE]);
),您将无法继续使用它!要么删除该语句,要么在关闭管道后退出循环。
问题 #2
open(pipe_descs[WRITE])
没有意义!摆脱那个。
问题 #3
[如果您的系统符合POSIX.1-2001,并且您写入的数量小于PIPE_BUF
,那么您可以忽略此部分。]
write(..., sizeof(int)) != sizeof(int)
不(必然)指示错误情况。如果没有发生错误,那么 write
没有将 errno
设置为有意义的内容,因此您获得的错误消息没有意义。
由于write
写的少于请求的数量不是错误,所以需要在循环中调用它。替换
if(write(pipe_descs[WRITE], &x, sizeof(int)) != sizeof(int)){
perror("write failed");
exit(EXIT_FAILURE);
}
和
my_write(pipe_descs[WRITE], &x, sizeof(x));
并添加
void my_write(int fd, const void *buf, size_t bytes_to_write) {
while (bytes_to_write > 0) {
ssize_t bytes_written = write(fd, buf, bytes_to_write);
if (bytes_written == -1) {
perror("write failed");
exit(EXIT_FAILURE);
}
buf += bytes_written;
bytes_to_write -= bytes_written;
}
}
类似的,read
到return小于请求的数量不是错误。因此,它也需要在 a 循环中调用。替换
while((pipestat = read(pipe_descs[READ], &readNum, sizeof(int))) > 0){
printf("read: %d \n", readNum);
//close(pipe_descs[READ]);
//open(pipe_descs[READ]);
}
if (pipestat==-1) {
perror("");
fprintf(stderr, "error to pipe... exiting\n");
exit(EXIT_FAILURE);
}
和
while (my_read(pipe_descs[READ], &readNum, sizeof(readNum))) {
printf("read: %d \n", readNum);
}
并添加
int my_read(int fd, void *buf, size_t bytes_to_read) {
int has_read = 0;
while (bytes_to_read > 0) {
ssize_t bytes_read = read(fd, buf, bytes_to_read);
if (bytes_read == -1) {
perror("read failed");
exit(EXIT_FAILURE);
}
if (bytes_read == 0) {
if (has_read) {
fprintf(stderr, "read failed: Premature EOF");
exit(EXIT_FAILURE);
}
return 0;
}
has_read = 1;
buf += bytes_read;
bytes_to_read -= bytes_read;
}
return 1;
}
我正在尝试让两个 child 进程通过管道相互通信。
一个 child 应该继续从 stdin 读取,将读取的内容传递给管道,而另一个 child 应该从管道读取并将其打印到 stdout。
我设法让它工作,但只有一次,在读取数字后的第二次迭代中,我得到:write failed: Bad file descriptor
。
我不知道我做错了什么...
#define READ 0
#define WRITE 1
int main(){
int pipe_descs[2];
int retval = pipe(pipe_descs);
int pid = fork();
if(pid == 0){ //son that reads from stdin and writes to pipe
close(pipe_descs[READ]);
int x;
while(1){
open(pipe_descs[WRITE]);
scanf("%d", &x);
if(write(pipe_descs[WRITE], &x, sizeof(int)) != sizeof(int)){
perror("write failed");
exit(EXIT_FAILURE);
}
close(pipe_descs[WRITE]);
}
perror("");
}
else if(pid > 0){ //parent
int pid = fork();
if(pid == 0){ //son that reads from pipe and write to stdout
int pipestat;
int readNum;
close(pipe_descs[WRITE]);
while((pipestat = read(pipe_descs[READ], &readNum, sizeof(int))) > 0){
printf("read: %d \n", readNum);
//close(pipe_descs[READ]);
//open(pipe_descs[READ]);
}
if (pipestat==-1) {
perror("");
fprintf(stderr, "error to pipe... exiting\n");
exit(EXIT_FAILURE);
}
}
}
int status;
int i = 2;
while (i > 0){
wait(&status);
i--;
}
}
问题 #1
如果您要关闭编写器(close(pipe_descs[WRITE]);
),您将无法继续使用它!要么删除该语句,要么在关闭管道后退出循环。
问题 #2
open(pipe_descs[WRITE])
没有意义!摆脱那个。
问题 #3
[如果您的系统符合POSIX.1-2001,并且您写入的数量小于PIPE_BUF
,那么您可以忽略此部分。]
write(..., sizeof(int)) != sizeof(int)
不(必然)指示错误情况。如果没有发生错误,那么 write
没有将 errno
设置为有意义的内容,因此您获得的错误消息没有意义。
由于write
写的少于请求的数量不是错误,所以需要在循环中调用它。替换
if(write(pipe_descs[WRITE], &x, sizeof(int)) != sizeof(int)){
perror("write failed");
exit(EXIT_FAILURE);
}
和
my_write(pipe_descs[WRITE], &x, sizeof(x));
并添加
void my_write(int fd, const void *buf, size_t bytes_to_write) {
while (bytes_to_write > 0) {
ssize_t bytes_written = write(fd, buf, bytes_to_write);
if (bytes_written == -1) {
perror("write failed");
exit(EXIT_FAILURE);
}
buf += bytes_written;
bytes_to_write -= bytes_written;
}
}
类似的,read
到return小于请求的数量不是错误。因此,它也需要在 a 循环中调用。替换
while((pipestat = read(pipe_descs[READ], &readNum, sizeof(int))) > 0){
printf("read: %d \n", readNum);
//close(pipe_descs[READ]);
//open(pipe_descs[READ]);
}
if (pipestat==-1) {
perror("");
fprintf(stderr, "error to pipe... exiting\n");
exit(EXIT_FAILURE);
}
和
while (my_read(pipe_descs[READ], &readNum, sizeof(readNum))) {
printf("read: %d \n", readNum);
}
并添加
int my_read(int fd, void *buf, size_t bytes_to_read) {
int has_read = 0;
while (bytes_to_read > 0) {
ssize_t bytes_read = read(fd, buf, bytes_to_read);
if (bytes_read == -1) {
perror("read failed");
exit(EXIT_FAILURE);
}
if (bytes_read == 0) {
if (has_read) {
fprintf(stderr, "read failed: Premature EOF");
exit(EXIT_FAILURE);
}
return 0;
}
has_read = 1;
buf += bytes_read;
bytes_to_read -= bytes_read;
}
return 1;
}