4. read()、write() 相关函数解析

我们在前面讲到了file_operations,其是一个函数指针的集合,用于存放我们定义的用于操作设备的函数的指针,如果我们不定义,它默认保留为NULL。其中有最重要的几个函数,分别是open()、read()、write()、ioctl(),下面分别对其进行解析

一、 打开和关闭设备函数a -- 打开设备

int (open) (struct inode , struct file );
在操作设备前必须先调用open函数打开文件,可以干一些需要的初始化操作。当然,如果不实现这个函数的话,驱动会默认设备的打开永远成功。打开成功时open返回0。b -- 关闭设备
int (
release) (struct inode , struct file );
当设备文件被关闭时内核会调用这个操作,当然这也可以不实现,函数默认为NULL。关闭设备永远成功。这两个函数已经讲过,这里不再赘述,主要看下面几个函数

二、read()、write() 函数

现在把 read()、write() 两个函数放一起讲,因为两个函数非密不可分的,先看一下两个函数的定义
a -- read() 函数

b -- write() 函数

两个函数的作用分别是 从设备中获取数据及发送数据给设备,应用程序中与之对应的也有 write() 函数及 read() 函数:

我们知道,应用程序工作在用户空间,而驱动工作在内核空间,二者不能直接通信的,那我们用何种方法进行通信呢?下面介绍一下内核中的memcpy---copy_from_user和copy_to_user,虽然说内核中不能使用C库提供的函数,但是内核也有一个memcpy的函数,用法跟C库中的一样。

可以看到两个函数均是调用了_memcpy() 函数:

既然拷贝的功能__memcpy函数就可以实现,为什么还要封装成copy_to_user和copy_from_user。
因为_memcpy有缺陷,比如当我们在引用层调用函数是传入的不是字符串,而是一个不能访问否则修改的地址。那样就会造成系统崩溃。
出于上面的原因,内核和用户态之间交互的数据时必须要先对数据进行检测,如果数据是安全的,才可以进行数据交互。
上面的函数就是memcpy的改进版,在memcpy功能的基础上加上的检查传入参数的功能,防止有些人有意或者无意的传入无效的参数。

现在我们可以审视一下这两个函数了:

用法:和memcpy的参数一样,但它根据传参方向的不同分开了两个函数。
"to"是相对于内核态来说的。所以,to函数的意思是从from指针指向的数据将n个字节的数据传到to指针指向的数据。
"from"也是相对于内核来说的。所以,from函数的意思是从from指针指向的数据将n个字节的数据传到to指针指向的数据。
返回值:函数的返回值是指定要读取的n个字节中还剩下多少字节还没有被拷贝。
注意:一般的,如果返回值不为0时,调用copy_to_user的函数会返回错误号-EFAULT表示操作出错。当然也可以自己决定。到这里open、close、read、write四个函数已经学完,
下面我们来看一下四个函数使用时,到底经历了一个怎样的过程:注:箭头方向是从调用的一方指向受作用的一方
************************代理****************************

扫描二维码关注公众号,回复: 1819993 查看本文章

猜你喜欢

转载自www.cnblogs.com/Ocean-Star/p/9249889.html