fcntl可实现对指定文件描述符的各种操作,其函数原型如下:
int fcntl(int fd, int cmd, ... /* arg */ );
头文件
#include#include
操作类型由cmd决定,cmd的取值如下:
- F_DUPFD:复制文件描述符
- F_DUPFD_CLOEXEC:复制文件描述符,新文件描述符被设置了close-on-exec
- F_GETFD:读取文件描述标识
- F_SETFD:设置文件描述标识
- F_GETFL:读取文件状态标识
- F_SETFL:设置文件状态标识
- F_GETLK:如果已经被加锁,返回该锁的数据结构。如果没有被加锁,将l_type设置为F_UNLCK
- F_SETLK:给文件加上进程锁
- F_SETLKW:给文件加上进程锁,如果此文件之前已经被加了锁,则一直等待锁被释放。
下面举个例子:
我们知道如果read没有读到数据会阻塞,但加入NONBLOCK描述符后就不会阻塞。
read_stdin.c
#includevoid changeNonblock(int fd){ int status = fcntl(fd, F_GETFL);//先用F_GETFL拿出原有属性 status = status|O_NONBLOCK;//再加入非阻塞属性 fcntl(fd, F_SETFL, status);//重置属性}int main(){ sleep(5); char buf[128] = {0}; int ret; changeNonblock(0); ret = read(STDIN_FILENO, buf, sizeof(buf)); printf("ret = %d, buf = %s\n", ret, buf); return 0;}
在输入hello后过了几秒(五秒内),打印出结果并退出。
另外如果想清空所有文件描述符可以和自己的非按位与:
#includevoid changeNonblock(int fd){ int status = fcntl(fd, F_GETFL); status = status|O_NONBLOCK; fcntl(fd, F_SETFL, status);}void clr_flag(int fd){ int status = fcntl(fd, F_GETFL); status &= ~status;//按位与清空文件描述符 fcntl(fd, F_SETFL, status);}int main(){ //sleep(5); char buf[128] = {0}; int ret; //changeNonblock(0); clr_flag(0); ret = read(0, buf, sizeof(buf)); printf("ret = %d, buf = %s\n", ret, buf); return 0;}