当前位置:网站首页 > 技术博客 > 正文

linux defunct



一、fcntl()函数

1. 函数的原型
 
  • 函数说明:fcntl()用来操作文件描述词的一些特性
  • 函数功能:可以改变已经打开文件的性质
  • 参数说明:
    • fd:代表欲设置的文件描述符
    • cmd:代表欲操作的指令。针对cmd的值,fcntl能够接受第三个参数int arg。有以下几种情况:
      • F_DUPFD:用来查找大于或等于参数 arg 的最小且仍未使用的文件描述符,并且复制参数 fd 的文件描述符。执行成功则返回新复制的文件描述符。请参考dup2()。复制文件描述符,新的文件描述符作为函数返回值返回。
      • F_GETFD:获取文件描述符,通过第三个参数设置
      • F_SETFD:设置文件描述符,通过第三个参数设置
      • F_GETFL/F_SETFL:
        • 取得/设置文件状态标志,通过第三个参数设置
        • 可以更改的几个标志是:O_APPEND、O_NONBLOCK、SYNC、O_ASYNC(O_RDONLY、O_WRONLY和O_RDWR不适用)
      • F_GETLK 取得文件锁定的状态。
      • F_SETLK 设置文件锁定的状态。此时flcok 结构的l_type 值必须是F_RDLCK、F_WRLCK或F_UNLCK。如果无法建立锁定,则返回-1,错误代码为EACCES 或EAGAIN。
      • F_SETLKW F_SETLK 作用相同,但是无法建立锁定时,此调用会一直等到锁定动作成功为止。若在等待锁定的过程中被信号中断时,会立即返回-1,错误代码为EINTR。
  • 参数lock指针为flock 结构指针,定义在下面。
  • 返回值:
    • 成功则返回0,若有错误则返回-1,错误原因存于errno。
  • 常见的功能:
    • 复制一个现存的描述符,新文件描述符作为函数返回值(cmd = F_DUPFD)
    • 获得/设置文件描述符标志(cmd = F_GETFD 或 F_SETFD)
    • 获得/设置文件状态标志(cmd = F_GETFL 或 F_SETFL)
    • 获得/设置文件锁(cmd = F_SETLK、cmd= F_GETLK、F_SETLKW)
  • 文件记录锁是fcntl函数的主要功能。
    • 记录锁:实现只锁文件的某个部分,并且可以灵活的选择是阻塞方式还是立刻返回方式
  • 当fcntl用于管理文件记录锁的操作时,第三个参数指向一个struct flock *lock的结构体
 
  • l_type 有三种状态:
    • F_RDLCK 建立一个供读取用的锁定
    • F_WRLCK 建立一个供写入用的锁定
    • F_UNLCK 删除之前建立的锁定
  • l_whence 也有三种方式:
    • SEEK_SET 以文件开头为锁定的起始位置。
    • SEEK_CUR 以目前文件读写位置为锁定的起始位置
    • SEEK_END 以文件结尾为锁定的起始位置。

注意事项:

  • short_l_type用来指定设置共享锁(F_RDLCK,读锁)还是互斥锁(F_WDLCK,写锁)。
    当short_l_type的值为F_UNLCK时,传入函数中将解锁。
    每个进程可以在该字节区域上设置不同的读锁。
    但给定的字节上只能设置一把写锁,并且写锁存在就不能再设其他任何锁,且该写锁只能被一个进程单独使用。
    这是多个进程的情况。
    单个进程时,文件的一个区域上只能有一把锁,若该区域已经存在一个锁,再在该区域设置锁时,新锁会覆盖掉旧的锁,无论是写锁还时读锁。
  • l_whence,l_start,l_len三个变量来确定给文件上锁的区域。
    l_whence确定文件内部的位置指针从哪开始,l_star确定从l_whence开始的位置的偏移量,两个变量一起确定了文件内的位置指针先所指的位置,即开始上锁的位置,然后l_len的字节数就确定了上锁的区域。
    特殊的,当l_len的值为0时,则表示锁的区域从起点开始直至最大的可能位置,就是从l_whence和l_start两个变量确定的开始位置开始上锁,将开始以后的所有区域都上锁。
    为了锁整个文件,我们会把l_whence,l_start,l_len都设为0。
2. 案例
 

io.c

 

file_append.c

 

使用设置文件状态标志,将文件标志的状态更改成为O_APPEND。也可清除相关的文件状态标志,就会出现被覆盖的现象。更改为O_APPEND的运行结果如下:
在这里插入图片描述

二、ioctl()函数

1. ioctl()函数

ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。

 
  • 函数说明:
    • ioctl函数是文件结构中的一个属性分量,就是说如果你的驱动程序提供了对ioctl的支持,用户就能在用户程序中使用ioctl函数 控制设备的I/O通道。
    • 此函数可以说是 I/O操作的杂物箱。不能用前面说的函数表示的 I/O 操作通常都能用 ioctl 表示。
    • 终端 I/O 是 ioctl 的最大使用方面,主要用于设备 I/O 控制
  • 函数功能:
    • 控制I/O设备 ,提供了一种获得设备信息和向设备发送控制参数的手段。
    • 用于向设备发控制和配置命令 ,有些命令需要控制参数,这些数据是不能用read / write 读写的,称为Out-of-band数据。
    • 也就是说,read / write 读写的数据是in-band数据,是I/O操作的主体,而ioctl 命令传送的是控制信息,其中的数据是辅助的数据。
  • 参数说明:
    • fd :就是用户程序打开设备时使用open函数返回的文件标示符,
    • cmd :就是用户程序对设备的控制命令,
    • … : 省略号,那是一些补充参数,即可变参数列表,一般最多一个,有或没有是和cmd的意义相关的。
  • 返回值:成功为0,出错为-1
2. ioctl的必要性

如果不用ioctl的话,也可以实现对设备I/O通道的控制,但那是蛮拧了。例如,我们可以在驱动程序中实现write的时候检查一下是否有特殊约定的数据流通过,如果有的话,那么后面就跟着控制命令(一般在socket编程中常常这样做)。但是如果这样做的话,会导致代码分工不明,程序结构混乱,程序员自己也会头昏眼花的。所以,我们就使用ioctl来实现控制的功能。要记住,用户程序所作的只是通过命令码(cmd)告诉驱动程序它想做什么,至于怎么解释这些命令和怎么实现这些命令,这都是驱动程序要做的事情。

3. 案例

从键盘 IO 设备中,读取键盘的数据。

 

运行结果如下:
在这里插入图片描述

版权声明


相关文章:

  • csrf攻击解决方案2024-11-16 08:30:01
  • visual develop2024-11-16 08:30:01
  • jinja2中文手册2024-11-16 08:30:01
  • flowable入门教程2024-11-16 08:30:01
  • 单元测试基本步骤2024-11-16 08:30:01
  • 过滤器和拦截器哪个先执行2024-11-16 08:30:01
  • idea创建xml配置文件2024-11-16 08:30:01
  • unity协程会阻塞主线程吗2024-11-16 08:30:01
  • 建立指标体系的步骤2024-11-16 08:30:01
  • usb协议大全2024-11-16 08:30:01