• 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四个函数已经学完,
    下面我们来看一下四个函数使用时,到底经历了一个怎样的过程:注:箭头方向是从调用的一方指向受作用的一方
    代理****

  • 相关阅读:
    harbor私有仓库搭建
    为普通用户添加sudo权限
    进程节点占用磁盘空间
    influxdb做prometheus永久存储
    prometheus监控linux进程
    Redis一主两从搭建
    ELK搭建
    redis geo操作
    k8s 1.16.3 yaml声明变化
    k8s启动Pod遇到CrashLoopBackOff的解决方法
  • 原文地址:https://www.cnblogs.com/Ocean-Star/p/9249889.html
Copyright © 2020-2023  润新知