Linux 高级 IO
非阻塞 IO:fcntl
fcntl 是 Linux 系统编程中一个非常重要的函数,全称为 File Control,即文件控制。它提供了对文件描述符的广泛控制,包括复制文件描述符、获取/设置文件描述符标志、获取/设置文件锁以及获取/设置文件描述符的所有者等。
一个文件描述符默认都是阻塞 IO,函数原型如下:
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, .../* arg */);
后面追加的参数根据 cmd 的值的不同而产生不同。
fcntl 函数有 5 种功能:
- 复制一个现有的描述符(cmd=F_DUPFD)
- 获得/设置文件描述符标记 (cmd=F_GETFD 或 F_SETFD)
- 获得/设置文件状态标记 (cmd=F_GETFL 或 F_SETFL)
- 获得/设置异步 I/O 所有权 (cmd=F_GETOWN 或 F_SETOWN)
- 获得/设置记录锁 (cmd=F_GETLK, F_SETLK 或 F_SETLKW)
我们现在只需要使用第三个功能,就能满足当前需要,将一个文件描述符设置为非阻塞。
实现函数 SetNoBlock
基于 fcntl,我们实现一个 SetNoBlock 函数,将文件描述符设置为非阻塞。
void SetNoBlock(int fd){
int fl = fcntl(fd, F_GETFL);
if(fl < 0){
perror("fcntl");
return;
}
fcntl(fd, F_SETFL, fl | O_NONBLOCK);
}
- 使用 F_GETFL 将当前的文件描述符的属性取出来
- 然后再使用 F_SETFL 将文件描述符设置回去。设置回去的同时,加上一个 O_NONBLOCK 参数,O_NONBLOCK 就是设置非阻塞
轮询方式读取标准输入
#include <iostream>
#include <stdio.h>
{
fl = (fd, F_GETFL);
(fl < ){
std::cerr << << std::endl;
();
}
(fd, F_SETFL, fl | O_NONBLOCK);
}
{
();
(){
buffer[];
s = (, buffer, (buffer));
(s > ){
buffer[s] = ;
std::cout << << buffer << std::endl;
} (s == ){
std::cout << << std::endl;
;
}{
(errno == EWOULDBLOCK){
std::cout << << errno << std::endl;
} (errno == EINTR){
std::cout << << std::endl;
}{
std::cout << << std::endl;
;
}
}
();
}
;
}


