open和release
open方法
提供给驱动程序以初始化的能力,open方法应完成以下工作
检查设备特定的错误
如果设备是首次打开,则对其进行初始化工作
如有必要,更新f_op组件
分配并填写置于filp->private_data里的数据结构
inode: 在其i_cdev字段中包含了我们想要的信息
file: 文件指针
我们指向得到包含某cdev结构体的scull_dev结构体,可以通过以下方法
经过简化的scuall_open
release方法
任务:
释放由open分配的,保存在file->private_data中的所有内容
在最后一次关闭操作时关闭设备
scull内存使用
试图分配size个字节大小的内存,其返回值指向该内存的指针,分配失败的时候返回NULL
flags参数用来描述内存的分配方法
释放kmalloc分配的空间
read和write
filp 是文件指针
count 是请求传输数据的长度
buff 是指向用户空间的缓冲区
offp 指明用户在文件中进行存取操作的位置(long offset type)
内核代码不能直接引用buff中的内容:
用户空间的地址可能是无效的;
内存可能不再ram中,造成oops错误
遭到恶意程序打开后门
用户地址空间和内核地址空间数据的交换
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
处理向量的函数
/* 把各个缓冲区的内容收集起来, 并将它们在第一次写入操作中进行输出 */
open方法
提供给驱动程序以初始化的能力,open方法应完成以下工作
检查设备特定的错误
如果设备是首次打开,则对其进行初始化工作
如有必要,更新f_op组件
分配并填写置于filp->private_data里的数据结构
- int (*open)(struct inode *inode, struct file *filep);
inode: 在其i_cdev字段中包含了我们想要的信息
file: 文件指针
我们指向得到包含某cdev结构体的scull_dev结构体,可以通过以下方法
- int (*open)(struct inode *inode, struct file *filep);
- struct scull_dev *dev;
- dev = container_of(inode->i_cdev, struct scull_dev, cdev);
- filp ->private_data = dev;
经过简化的scuall_open
- int scuall_open(struct inode *inode, struct file* filp)
- {
- struct scull_dev *dev;
- dev = container_of(inode->i_cdev, struct scull_dev, cdev);
- filp->private_data = dev;
- if ((filp->f_flags & O_ACCMODE) == O_WRONLY) {
- scull_trim(dev);
- }
- return 0;
- }
release方法
任务:
释放由open分配的,保存在file->private_data中的所有内容
在最后一次关闭操作时关闭设备
- int scull_release(struct inode *inode, struct file* filp);
scull内存使用
- void *kmalloc(size_t size, int flags);
试图分配size个字节大小的内存,其返回值指向该内存的指针,分配失败的时候返回NULL
flags参数用来描述内存的分配方法
- void kfree(void *ptr);
释放kmalloc分配的空间
read和write
- ssize_t read(struct file *filp, char __user *buff,
- size_t count, loff_t *offp);
- /*拷贝数据到应用程序空间*/
- ssize_t write(struct file *filp, char __user *buff,
- size_t count, loff_t *offp);
- /*从应用程序空间拷贝数据*/
filp 是文件指针
count 是请求传输数据的长度
buff 是指向用户空间的缓冲区
offp 指明用户在文件中进行存取操作的位置(long offset type)
内核代码不能直接引用buff中的内容:
用户空间的地址可能是无效的;
内存可能不再ram中,造成oops错误
遭到恶意程序打开后门
用户地址空间和内核地址空间数据的交换
- unsigned long copy_to_user(void __user *to,
- const void *from,
- unosigned long count);
- /*将数据拷贝到用户空间*/
- unsigned long copy_from_user(void *to,
- const void __user *from,
- unsigned long count);
- /*从用户空间将数据考到内核空间*/
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
处理向量的函数
- ssize_t (*readv) (struct file *filp, const struct iovec *lov,
- unsigned long count, loof_t *ppos);
- /* 将指定数量的数据依次读入每个缓冲区*/
- ssize_t (*writev) (struct file *filp, const struct iovec *lov,
- unsigned long count, loof_t *ppos);
/* 把各个缓冲区的内容收集起来, 并将它们在第一次写入操作中进行输出 */
- struct iovec {
- void __user *iov_base;
- __kernel_size_t iov_len;
- };