我目前正在尝试用C语言编写一个程序,该程序将从两个命名管道中读取并在stdout可用时将任何数据打印到stdout.
例如:如果我打开两个终端并./execute pipe1 pipe2在其中一个终端(管道1和管道2是有效的命名管道)然后键入管道echo "Data here." > pipe1的名称(这里是pipe1),大小和数据应打印到stdout- - 这里看起来像pipe1 [25]: Data here.
我知道我需要用O_RDONLY和O_NONBLOCK旗子打开管道.我已经看过许多人使用的例子(在这个论坛上有很多),select()我仍然不明白传递的不同参数select()是做什么的.如果有人可以在这里提供指导,那将非常有帮助.下面是我到目前为止的代码.
int pipeRouter(char[] fifo1, char[] fifo2){
fileDescriptor1 = open(fifo1, O_RDONLY, O_NONBLOCK);
fileDescriptor2 = open(fifo2, O_RDONLY, O_NONBLOCK);
if(fileDescriptor1 < 0){
printf("%s does not exist", fifo1);
}
if(fileDescriptor2 < 0){
printf("%s does not exist", fifo2);
}
}
Run Code Online (Sandbox Code Playgroud)
将select让你等待I/O事件,而不是在缩腰的CPU周期read.
因此,在您的示例中,主循环可能如下所示:
for (;;)
{
int res;
char buf[256];
res = read(fileDescriptor1, buf, sizeof(buf));
if (res > 0)
{
printf("Read %d bytes from channel1\n", res);
}
res = read(fileDescriptor2, buf, sizeof(buf));
if (res > 0)
{
printf("Read %d bytes from channel2\n", res);
}
}
Run Code Online (Sandbox Code Playgroud)
如果您添加代码并运行它,您会注意到:
解决问题,select并poll引入API.因为select我们需要知道描述符(我们这样做),以及最大限度的描述符.
所以让我们稍微修改一下代码:
for (;;)
{
fd_set fds;
int maxfd;
FD_ZERO(&fds); // Clear FD set for select
FD_SET(fileDescriptor1, &fds);
FD_SET(fileDescriptor2, &fds);
maxfd = fileDescriptor1 > fileDescriptor2 ? fileDescriptor1 : fileDescriptor2;
select(maxfd + 1, &fds, NULL, NULL, NULL);
// The minimum information for select: we are asking only about
// read operations, ignoring write and error ones; and not
// defining any time restrictions on wait.
// do reads as in previous example here
}
Run Code Online (Sandbox Code Playgroud)
当运行改进的代码时,CPU不会浪费太多,但你会注意到,read即使没有特定管道的数据,也会执行操作,但还有另一个.
要检查哪个管道实际上有数据,请FD_ISSET在select调用后使用:
if (FD_ISSET(fileDescriptor1, &fds))
{
// We can read from fileDescriptor1
}
if (FD_ISSET(fileDescriptor2, &fds))
{
// We can read from fileDescriptor2
}
Run Code Online (Sandbox Code Playgroud)
因此,在加入上述内容后,代码看起来像:
for (;;)
{
fd_set fds;
int maxfd;
int res;
char buf[256];
FD_ZERO(&fds); // Clear FD set for select
FD_SET(fileDescriptor1, &fds);
FD_SET(fileDescriptor2, &fds);
maxfd = fileDescriptor1 > fileDescriptor2 ? fileDescriptor1 : fileDescriptor2;
select(maxfd + 1, &fds, NULL, NULL, NULL);
if (FD_ISSET(fileDescriptor1, &fds))
{
// We can read from fileDescriptor1
res = read(fileDescriptor1, buf, sizeof(buf));
if (res > 0)
{
printf("Read %d bytes from channel1\n", res);
}
}
if (FD_ISSET(fileDescriptor2, &fds))
{
// We can read from fileDescriptor2
res = read(fileDescriptor2, buf, sizeof(buf));
if (res > 0)
{
printf("Read %d bytes from channel2\n", res);
}
}
}
Run Code Online (Sandbox Code Playgroud)
因此,添加错误处理,您将被设置.