LINUX中,管道的读写两端是阻塞的,例如读端会一直阻塞直到写端写入内容,才会立即返回。其实也可以将管道中的读或写端设置为非阻塞状态。
如果要设置读端或者写端为非阻塞,参考以下三个步骤:
- int flags = fcntl(fd[0], F_GETFL, 0);
- flag |= O_NONBLOCK;
- fcntl(fd[0], F_SETFL, flags);
以读端设置为非阻塞为例:
- 写端没有关闭,管道中没有数据可读,则read返回-1
- 写端没有关闭,管道中有数据可读,则read返回实际读到的字节数
- 写端已经关闭,管道中有数据可读,则read返回实际读到的字节数
- 写端已经关闭,管道中没有数据可读,则read返回0
以一个程序为例,验证read的是否返回值如上所罗列
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
using namespace std;
int main()
{
//创建管道
//int pipe(int pipefd[2]);
int fd[2];
int ret = pipe(fd);
if(ret<0)
{
perror("pipe error");
return -1;
}
//close(fd[0]);
//write(fd[1], "hello world", strlen("hello world"));
//关闭写端
close(fd[1]);
//设置管道的读端为非阻塞
int flag = fcntl(fd[0], F_GETFL);
flag |= O_NONBLOCK;
fcntl(fd[0], F_SETFL, flag);
char buf[64];
memset(buf, 0x00, sizeof(buf));
int n = read(fd[0], buf, sizeof(buf));
cout << "read over, n==[" << n << "], buf==[" << buf << "]" << endl;
return 0;
}
执行结果如下:
验证了上述的第四种情况。
以第三种情况为例:写端已经关闭,管道中有数据可读,则read返回实际读到的字节数
代码如下:
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
using namespace std;
int main()
{
//创建管道
//int pipe(int pipefd[2]);
int fd[2];
int ret = pipe(fd);
if(ret<0)
{
perror("pipe error");
return -1;
}
//close(fd[0]);
write(fd[1], "hello world", strlen("hello world"));
//关闭写端
close(fd[1]);
//设置管道的读端为非阻塞
int flag = fcntl(fd[0], F_GETFL);
flag |= O_NONBLOCK;
fcntl(fd[0], F_SETFL, flag);
char buf[64];
memset(buf, 0x00, sizeof(buf));
int n = read(fd[0], buf, sizeof(buf));
cout << "read over, n==[" << n << "], buf==[" << buf << "]" << endl;
return 0;
}
结果如下:
读到了数据,验证成功!!