如何从 unix 管道建立非阻塞读取?
how to establish a non blocking read from unix pipes?
假设我们有一个管道 int InPipe[2];
。当读取整个可用数据输入时,如何在管道为空之前读取输入而不阻塞?
我知道这个问题已经被问过好几次了,但是我找不到assemble合适的函数。
到目前为止,这是我的代码:
int InPipe[2];
char buffer[1024];
int rc;
while (true){
read(InPipe[0], buffer, sizeof(buffer));
fprintf(stdout, “%s“, buffer);
bzero(&buffer, sizeof(buffer)); // Clearing Buffer
}
任何想法、建议、代码片段
从管道读取
Attempts to read from a pipe
that is currently empty block
until at
least one byte has been written to the pipe
. If the write end
of a pipe is closed, then a process reading from the pipe will
see end-of-file
(i.e., read()
returns 0) once it has read all remaining
data in the pipe
.
取自linux界面编程。
你不能!在这种情况下,从管道读取的进程将被阻塞。
由于人们的评论,我添加了这一部分:
我们可以使用 pipe
来允许两个进程之间的通信。要使用管道连接两个进程,我们在 pipe()
调用之后调用 fork()
。在 fork()
之后,一个进程立即关闭其管道写入端的描述符,另一个进程关闭其读取端的描述符。例如,如果父进程要向子进程发送数据,那么它将关闭管道的读描述符filedes[0]
,而子进程将关闭管道的写描述符filedes[1]
,然后代码为:
int filedes[2];
if (pipe(filedes) == -1) /* Create the pipe */
errExit("pipe");
switch (fork()) /* Create a child process */
{
case -1:
errExit("fork");
case 0: /* Child */
if (close(filedes[1]) == -1) /* Close unused write end */
errExit("close");
/* Child now reads from pipe */
break;
default: /* Parent */
if (close(filedes[0]) == -1) /* Close unused read end */
errExit("close");
/* Parent now writes to pipe */
break;
}
评论中提到了一些关键事项,即非阻塞 IO、在自己的线程中执行读取,以及其他一些建议。 The example here 详细解释了它的架构。下面只转载了代码部分,因为我认为它是对其中一些评论的一个很好的说明。示例代码在整个过程中都有注释。阅读它们,它们是一个很好的教程:
// C program to demonstrate use of fork() and pipe()
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
#include<sys/wait.h>
int main()
{
// We use two pipes
// First pipe to send input string from parent
// Second pipe to send concatenated string from child
int fd1[2]; // Used to store two ends of first pipe
int fd2[2]; // Used to store two ends of second pipe
char fixed_str[] = "forgeeks.org";
char input_str[100];
pid_t p;
if (pipe(fd1)==-1)
{
fprintf(stderr, "Pipe Failed" );
return 1;
}
if (pipe(fd2)==-1)
{
fprintf(stderr, "Pipe Failed" );
return 1;
}
scanf("%s", input_str);
p = fork(); //Note - the return of fork can be less than, greater
// than or equal to zero. Each is significant in
// knowing how to direct program flow, as shown
// in this section...
if (p < 0)
{
fprintf(stderr, "fork Failed" );
return 1;
}
// Parent process
else if (p > 0)
{
char concat_str[100];
close(fd1[0]); // Close reading end of first pipe
// Write input string and close writing end of first
// pipe.
write(fd1[1], input_str, strlen(input_str)+1);
close(fd1[1]);
// Wait for child to send a string
wait(NULL);
close(fd2[1]); // Close writing end of second pipe
// Read string from child, print it and close
// reading end.
read(fd2[0], concat_str, 100);
printf("Concatenated string %s\n", concat_str);
close(fd2[0]);
}
// child process
else
{
close(fd1[1]); // Close writing end of first pipe
// Read a string using first pipe
char concat_str[100];
read(fd1[0], concat_str, 100);
// Concatenate a fixed string with it
int k = strlen(concat_str);
int i;
for (i=0; i<strlen(fixed_str); i++)
concat_str[k++] = fixed_str[i];
concat_str[k] = '[=10=]'; // string ends with '[=10=]'
// Close both reading ends
close(fd1[0]);
close(fd2[0]);
// Write concatenated string and close writing end
write(fd2[1], concat_str, strlen(concat_str)+1);
close(fd2[1]);
exit(0);
}
}
假设我们有一个管道 int InPipe[2];
。当读取整个可用数据输入时,如何在管道为空之前读取输入而不阻塞?
我知道这个问题已经被问过好几次了,但是我找不到assemble合适的函数。
到目前为止,这是我的代码:
int InPipe[2];
char buffer[1024];
int rc;
while (true){
read(InPipe[0], buffer, sizeof(buffer));
fprintf(stdout, “%s“, buffer);
bzero(&buffer, sizeof(buffer)); // Clearing Buffer
}
任何想法、建议、代码片段
从管道读取
Attempts to read from a
pipe
that is currently emptyblock
until at least one byte has been written to thepipe
. If the write end of a pipe is closed, then a process reading from the pipe will seeend-of-file
(i.e.,read()
returns 0) once it has read all remaining data in thepipe
.
取自linux界面编程。
你不能!在这种情况下,从管道读取的进程将被阻塞。
由于人们的评论,我添加了这一部分:
我们可以使用 pipe
来允许两个进程之间的通信。要使用管道连接两个进程,我们在 pipe()
调用之后调用 fork()
。在 fork()
之后,一个进程立即关闭其管道写入端的描述符,另一个进程关闭其读取端的描述符。例如,如果父进程要向子进程发送数据,那么它将关闭管道的读描述符filedes[0]
,而子进程将关闭管道的写描述符filedes[1]
,然后代码为:
int filedes[2];
if (pipe(filedes) == -1) /* Create the pipe */
errExit("pipe");
switch (fork()) /* Create a child process */
{
case -1:
errExit("fork");
case 0: /* Child */
if (close(filedes[1]) == -1) /* Close unused write end */
errExit("close");
/* Child now reads from pipe */
break;
default: /* Parent */
if (close(filedes[0]) == -1) /* Close unused read end */
errExit("close");
/* Parent now writes to pipe */
break;
}
评论中提到了一些关键事项,即非阻塞 IO、在自己的线程中执行读取,以及其他一些建议。 The example here 详细解释了它的架构。下面只转载了代码部分,因为我认为它是对其中一些评论的一个很好的说明。示例代码在整个过程中都有注释。阅读它们,它们是一个很好的教程:
// C program to demonstrate use of fork() and pipe()
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
#include<sys/wait.h>
int main()
{
// We use two pipes
// First pipe to send input string from parent
// Second pipe to send concatenated string from child
int fd1[2]; // Used to store two ends of first pipe
int fd2[2]; // Used to store two ends of second pipe
char fixed_str[] = "forgeeks.org";
char input_str[100];
pid_t p;
if (pipe(fd1)==-1)
{
fprintf(stderr, "Pipe Failed" );
return 1;
}
if (pipe(fd2)==-1)
{
fprintf(stderr, "Pipe Failed" );
return 1;
}
scanf("%s", input_str);
p = fork(); //Note - the return of fork can be less than, greater
// than or equal to zero. Each is significant in
// knowing how to direct program flow, as shown
// in this section...
if (p < 0)
{
fprintf(stderr, "fork Failed" );
return 1;
}
// Parent process
else if (p > 0)
{
char concat_str[100];
close(fd1[0]); // Close reading end of first pipe
// Write input string and close writing end of first
// pipe.
write(fd1[1], input_str, strlen(input_str)+1);
close(fd1[1]);
// Wait for child to send a string
wait(NULL);
close(fd2[1]); // Close writing end of second pipe
// Read string from child, print it and close
// reading end.
read(fd2[0], concat_str, 100);
printf("Concatenated string %s\n", concat_str);
close(fd2[0]);
}
// child process
else
{
close(fd1[1]); // Close writing end of first pipe
// Read a string using first pipe
char concat_str[100];
read(fd1[0], concat_str, 100);
// Concatenate a fixed string with it
int k = strlen(concat_str);
int i;
for (i=0; i<strlen(fixed_str); i++)
concat_str[k++] = fixed_str[i];
concat_str[k] = '[=10=]'; // string ends with '[=10=]'
// Close both reading ends
close(fd1[0]);
close(fd2[0]);
// Write concatenated string and close writing end
write(fd2[1], concat_str, strlen(concat_str)+1);
close(fd2[1]);
exit(0);
}
}