fcntl() 在打开的文件描述符 FD 上执行下面描述的操作之一。 操作由 cmd 确定。
fcntl() 可以采用可选的第三个参数。 是否需要此参数由 cmd 确定。 所需的参数类型在后面的括号中指示。
每个cmd名称(在大多数情况下,所需的类型是int,我们使用名称arg来标识参数),或者如果不需要参数,则指定void。
下图是对是否需要设置可变参数的解释:
#include <iostream>#include <cstdlib>#include <unistd.h>#include <fcntl.h>#include <stdio.h>#include <cstring>#include <cerrno>void SetNonBlock(int fd){// 提取文件描述符属性(返回值是一个位图)int f1 = fcntl(0, F_GETFL);if (f1 < 0){perror("fcntl");return;}// 使用F_SETFL将文件描述符设置回去,加上O_NONBLOCK参数。fcntl(0, F_SETFL, f1 | O_NONBLOCK);}int main(){char buffer[1024];SetNonBlock(0); // 设置非阻塞。while (true)//轮询{sleep(1);printf(">>> ");fflush(stdout);ssize_t n = read(0, buffer, sizeof(buffer) - 1); // (检查条件是否就绪)等+拷贝if (n > 0){buffer[n - 1] = 0; // 因为从标准输入读取,回车键也会放入内核缓冲区,被上层读取。std::cout << "echo# " << buffer << std::endl;}else if (n == 0){std::cout << "end file" << std::endl;}else{// 区分是真正出错还是数据没有就绪这两种情况。if (errno == EAGAIN || errno == EWOULDBLOCK){// 底层数据没有就绪,希望你下次继续来检测std::cout<<"data not ready"<<std::endl;continue;}else if (errno == EINTR){// 这次I/O被信号中断,也需要重新读取continue;}else{//真正出错std::cout << "WARNING!!! ERRNO: " << errno << ",error: " << strerror(errno) << std::endl;break;}}}return 0;}