> 技术文档 > linux 驱动开发,file_operations 结构体_fileoperation结构体

linux 驱动开发,file_operations 结构体_fileoperation结构体

在 Linux 驱动开发中,struct file_operations 是字符设备驱动的核心接口,定义了驱动支持的所有文件操作(如 open/read/write)。它是驱动与用户空间交互的桥梁,每个函数对应一个系统调用。


1. 结构体定义

定义在  中,核心成员如下:

struct file_operations { loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); int (*open) (struct inode *, struct file *); int (*release) (struct inode *, struct file *); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); // 其他成员(如 poll、mmap 等)};

2. 关键成员函数

(1) open 和 release
  • open:首次打开设备时调用,用于初始化硬件或分配资源。

    static int my_open(struct inode *inode, struct file *file) { // 获取设备私有数据(如硬件寄存器地址) struct my_device *dev = container_of(inode->i_cdev, struct my_device, cdev); file->private_data = dev; // 初始化硬件... return 0;}
  • release:文件关闭时调用,释放资源。

    static int my_release(struct inode *inode, struct file *file) { struct my_device *dev = file->private_data; // 关闭硬件... return 0;}
(2) read 和 write
  • read:从设备读取数据到用户空间。

    static ssize_t my_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct my_device *dev = file->private_data; // 从硬件读取数据到内核缓冲区 copy_to_user(buf, dev->kernel_buffer, count); // 复制到用户空间 return count;}
  • write:将用户空间数据写入设备。

    static ssize_t my_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { struct my_device *dev = file->private_data; copy_from_user(dev->kernel_buffer, buf, count); // 从用户空间复制 // 写入硬件... return count;}
(3) unlocked_ioctl
  • 处理设备特定的控制命令(如配置寄存器)。
    static long my_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct my_device *dev = file->private_data; switch (cmd) { case MY_IOCTL_CMD: // 处理命令... return 0; default: return -EINVAL; }}

3. 驱动中的使用示例

// 1. 定义 file_operations 实例static const struct file_operations my_fops = { .owner = THIS_MODULE, .open = my_open, .release = my_release, .read = my_read, .write = my_write, .unlocked_ioctl = my_ioctl,};// 2. 注册字符设备static int __init my_init(void) { dev_t dev = MKDEV(major, 0); cdev_init(&my_cdev, &my_fops); return cdev_add(&my_cdev, dev, 1);}

4. 关键注意事项

  1. 线程安全

    • 使用互斥锁(如 mutex_lock)保护共享资源:
      static DEFINE_MUTEX(my_mutex);static int my_open(...) { mutex_lock(&my_mutex); // 初始化操作... mutex_unlock(&my_mutex); return 0;}
  2. 用户空间交互

    • 使用 copy_to_user/copy_from_user 安全访问用户内存。
    • 返回负数错误码(如 -EFAULT 表示内存错误)。
  3. 权限检查

    if (!capable(CAP_SYS_ADMIN)) return -EPERM; // 拒绝非特权用户访问
  4. 偏移量管理

    • 通过 loff_t *ppos 跟踪文件读写位置(如支持 lseek)。

5. 高级主题

  • 异步 I/O:实现 .aio_read/.aio_write 支持异步操作。
  • 轮询/select:实现 .poll 函数通知文件就绪状态。
  • 内存映射:通过 .mmap 将设备内存映射到用户空间。

总结

struct file_operations 是驱动与用户空间的接口契约。通过填充此结构体,驱动开发者将硬件操作映射到标准文件操作,使得用户空间程序可以通过 open()/read()/write() 等系统调用与设备交互。正确实现这些函数是编写稳定字符设备驱动的关键。