Linux系统调用五、fcntl函数与非阻塞

Linux系统调用五、fcntl函数与非阻塞Linux 系统调用系列文章第五篇 讲解了阻塞与非阻塞的概念以及 fcntl 函数的用法


在这里插入图片描述




?1. 阻塞与非阻塞概念

阻塞可能会发生在read()函数读取设备、读取管道或读取网络的时候,因为某种情况需要等待,而不会立即返回,叫做阻塞。下面通过read()读设备来演示,比如读输入输出设备 /dev/tty 。

我们先写一个测试函数来看一下阻塞的效果,让read()函数读取标准输入输出设备tty的内容,如果标准输入输出没有内容的话,read()函数就会被阻塞,直到tty有内容了,才会继续执行。

/ >File Name : read_tty.c >Author :  >Company :  >Create Time: 2022年05月13日 星期五 22时22分00秒 / #include  
       #include  
       #include  
       #include  
       #include  
       #include  
       int main() { 
      int fd = open("/dev/tty", O_RDONLY); char buf[100]; memset(buf, 0, sizeof(buf)); while(1) { 
      int ret = read(fd, buf, sizeof(buf)); printf("read return : %d\n", ret); if(ret > 0) { 
      printf("buf data : %s\n", buf); } printf("test : Because of blocking, not looping.\n"); } close(fd); return 0; } 
int main() { 
      int fd = open("/dev/tty", O_RDONLY | O_NONBLOCK); /*加O_NONBLOCK参数实现非阻塞*/ char buf[100]; memset(buf, 0, sizeof(buf)); while(1) { 
      int ret = read(fd, buf, sizeof(buf)); if(ret < 0) { 
      perror("read err: "); /*打印出错信息,read函数返回失败的时候会设置errno*/ } printf("read return : %d\n", ret); if(ret > 0) { 
      printf("buf data : %s\n", buf); } printf("test : Because of blocking, not looping.\n"); sleep(2); /*睡眠2秒,不然的话会一直刷屏*/ } close(fd); return 0; } 

?2. fcntl函数设置非阻塞

  • 包含头文件
#include  
       #include  
       
  • 函数原型
int fcntl(int fd, int cmd, ... /* arg */ ); 
  • 函数功能

    fcntl() performs one of the operations described below on the open file descriptor fd. The operation is determined by cmd. 打开一个文件描述符,操作由cmd来决定。这个函数功能还是很多的,可以通过 man 2 fcntl 来查看。

  • 函数参数

    它是一个可变参数的函数,… /* arg */ 的内容取决于cmd,比较常用的两个如下

    • 获取标志:F_GETFL (void) Read the file status flags; arg is ignored. 也就是说,如果cmd选择F_GETFL的话,后面参数可以为void,也就是没有第三个参数
    • 设置标志:F_SETFL (long) Set the file status flags to the value specified by arg. File access mode (O_RDONLY, O_WRONLY, O_RDWR) and file creation flags (i.e., O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC) in arg are ignored. On Linux this command can only change the O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK flags. 这个的话,如果cmd是F_SETFL,那么后边参数应该是long类型的
  • 函数返回值

    F_GETFL Value of flags. 如果我们使用的cmd参数是F_GETFL 那么就会把获取的标志返回出来。实际上,fcntl()函数的返回值也是由cmd参数来决定的,这只是比较常用的一个,更多的返回值可以在man手册查询。

下面我们通过实例来说明这个函数的用法,接上一节的话题,我们可以不在open()打开文件的时候设置非阻塞,而是在程序中使用fcntl()函数来设置非阻塞参数,具体代码如下。

int main() { 
      int fd = open("/dev/tty", O_RDONLY); /*第一次调用,使用F_GETFL来获取标志,并通过返回值返回*/ int flag = fcntl(fd, F_GETFL); /*把标志重新设置,通过或运算置非阻塞位*/ flag |= O_NONBLOCK; /*第二次调用,使用F_SETFL参数来设置标志位,把上面修改好的标志在设置回文件*/ fcntl(fd, F_SETFL, flag); char buf[100]; memset(buf, 0, sizeof(buf)); while(1) { 
      int ret = read(fd, buf, sizeof(buf)); if(ret < 0) { 
      perror("read err: "); } printf("read return : %d\n", ret); if(ret > 0) { 
      printf("buf data : %s\n", buf); } printf("test : Because of blocking, not looping.\n"); sleep(2); } close(fd); return 0; } 

在这里插入图片描述

在这里插入图片描述


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/209440.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 上午9:14
下一篇 2026年3月19日 上午9:14


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号