【内核&驱动】字符设备驱动程序【3】

本文详细解析了Linux内核中文件系统操作的关键函数open和release,以及如何进行内存分配与管理。通过简化示例,展示了如何在设备驱动程序中实现这些核心功能,确保文件系统操作的高效性和安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

open和release
open方法
提供给驱动程序以初始化的能力,open方法应完成以下工作
检查设备特定的错误
如果设备是首次打开,则对其进行初始化工作
如有必要,更新f_op组件
分配并填写置于filp->private_data里的数据结构


  1. int (*open)(struct inode *inode, struct file *filep);


inode: 在其i_cdev字段中包含了我们想要的信息
file: 文件指针

我们指向得到包含某cdev结构体的scull_dev结构体,可以通过以下方法

  1. int (*open)(struct inode *inode, struct file *filep);


  1. struct scull_dev *dev;
  2. dev = container_of(inode->i_cdev, struct scull_dev, cdev);
  3. filp ->private_data = dev;


经过简化的scuall_open

  1. int scuall_open(struct inode *inode, struct file* filp)
  2. {
  3. struct scull_dev *dev;

  4. dev = container_of(inode->i_cdev, struct scull_dev, cdev);
  5. filp->private_data = dev;

  6. if ((filp->f_flags & O_ACCMODE) == O_WRONLY) {
  7. scull_trim(dev);
  8. }
  9. return 0;
  10. }



release方法
任务:
释放由open分配的,保存在file->private_data中的所有内容
在最后一次关闭操作时关闭设备

  1. int scull_release(struct inode *inode, struct file* filp);



scull内存使用

  1. void *kmalloc(size_t size, int flags);

试图分配size个字节大小的内存,其返回值指向该内存的指针,分配失败的时候返回NULL
flags参数用来描述内存的分配方法

  1. void kfree(void *ptr);

释放kmalloc分配的空间

read和write

  1. ssize_t read(struct file *filp, char __user *buff,
  2. size_t count, loff_t *offp);
  3. /*拷贝数据到应用程序空间*/
  4. ssize_t write(struct file *filp, char __user *buff,
  5. size_t count, loff_t *offp);
  6. /*从应用程序空间拷贝数据*/


filp 是文件指针
count 是请求传输数据的长度
buff 是指向用户空间的缓冲区
offp 指明用户在文件中进行存取操作的位置(long offset type)

内核代码不能直接引用buff中的内容:
用户空间的地址可能是无效的;
内存可能不再ram中,造成oops错误
遭到恶意程序打开后门

用户地址空间和内核地址空间数据的交换

  1. unsigned long copy_to_user(void __user *to,
  2. const void *from,
  3. unosigned long count);
  4. /*将数据拷贝到用户空间*/
  5. unsigned long copy_from_user(void *to,
  6. const void __user *from,
  7. unsigned long count);
  8. /*从用户空间将数据考到内核空间*/



read和write发生错误的时候将返回一个负值
如果返回一个大于等于0的值则表示成功和操作的数据的字节数

read方法
调用程序对read的返回值的解释如下
返回值等于count,表示所请求的字节数成功并完全传输
返回值小于count,表示部分数据传输成功,传输的字节数小于请求的字节数
返回值等于0,表示传输达到了文件尾部
返回值小于0,表示发生了错误,错误码在<linux/errno.h>
-EINTR 系统调用被中断
-EFAULT 无效地址
或者现在还没有数据,但以后可能会有,read系统调用会被阻塞
write方法
调用程序对write的返回值的解释如下
返回值等于count,表示所请求的字节数成功并完全传输
返回值小于count,表示部分数据传输成功,传输的字节数小于请求的字节数
返回值等于0,表示什么也没有写入
返回值小于0,表示发生了错误,错误码在<linux/errno.h>
-EINTR 系统调用被中断
-EFAULT 无效地址

readv和writev
处理向量的函数

  1. ssize_t (*readv) (struct file *filp, const struct iovec *lov,
  2. unsigned long count, loof_t *ppos);
  3. /* 将指定数量的数据依次读入每个缓冲区*/
  4. ssize_t (*writev) (struct file *filp, const struct iovec *lov,
  5. unsigned long count, loof_t *ppos);


/* 把各个缓冲区的内容收集起来, 并将它们在第一次写入操作中进行输出 */


  1. struct iovec {
  2. void __user *iov_base;
  3. __kernel_size_t iov_len;
  4. };

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值