fcntl() 在打开的文件描述符 FD 上执行下面描述的操作之一。 操作由 cmd 确定。
fcntl() 可以采用可选的第三个参数。 是否需要此参数由 cmd 确定。 所需的参数类型在后面的括号中指示。
每个cmd名称(在大多数情况下,所需的类型是int,我们使用名称arg来标识参数),或者如果不需要参数,则指定void。
下图是对是否需要设置可变参数的解释:
- #include
-
- #include
-
- #include
-
- #include
-
- #include
-
- #include
-
- #include
-
- 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"<
-
- continue;
-
- }
-
-
-
- else if (errno == EINTR)
-
- {
-
- // 这次I/O被信号中断,也需要重新读取
-
- continue;
-
- }
-
- else
-
- {
-
- //真正出错
-
- std::cout << "WARNING!!! ERRNO: " << errno << ",error: " << strerror(errno) << std::endl;
-
- break;
-
- }
-
- }
-
- }
-
-
-
- return 0;
-
- }