从系统调用到设备驱动:详解open、syscall_open和drv_open

open系统调用、syscall_open函数和drv_open函数之间的联系和区别
  1. open 系统调用

    • 角色:用户空间的系统调用接口,用于打开文件或设备。

    • 作用:这是用户程序用来请求打开文件的接口。用户程序通过调用 open 系统调用(如 open("/dev/mydevice", O_RDWR))来打开文件或设备,获取一个文件描述符。

    • 实现open 系统调用在用户空间的C标准库(如 glibc)中实现,会触发内核中的相应处理函数陷入内核空间,最终调用具体的文件或设备驱动程序的 open 实现。

    • 示例

      int fd = open("/dev/my_device", O_RDWR);
      
  2. syscall_open 函数

    • 角色:位于内核空间,是内核中的系统调用处理函数,是 open 系统调用在内核中的实现。

    • 作用syscall_open 是内核处理 open 系统调用的入口点。它负责解析用户空间传入的参数(如文件路径、打开标志等),并调用与文件或设备关联的 file_operations 结构体中具体的驱动程序的 open 方法,即 drv_open来打开文件。

    • 实现syscall_open 通常由内核开发者实现,是内核的一个内部函数。

    • 示例

      // 内核中系统调用处理函数的简化示例
      long sys_open(const char __user *filename, int flags, umode_t mode) {
          // 查找文件路径,获取 inode 和 file 结构体
          struct file *filp = do_filp_open(AT_FDCWD, filename, flags);
          // 调用文件的 open 方法
          return finish_open(filp, NULL, O_RDWR);c
      }
  3. drv_open 函数

    • 角色drv_open 位于具体的设备驱动程序代码中,是设备驱动程序中的具体实现函数,是 file_operations 结构体中的一个函数指针。

    • 作用drv_open 是具体设备驱动程序实现的 open 方法。它执行与设备打开相关的具体操作,如初始化设备、分配资源等。

    • 实现drv_open 由设备驱动开发者实现,作为 file_operations 结构体中的 open 方法,主要功能是执行设备特定的操作,如初始化硬件、分配设备资源、设置设备状态等。

    • 示例

      // 设备驱动程序中的 open 方法实现
      static int drv_open(struct inode *inode, struct file *filp) {
          // 设备特定的初始化操作
          printk(KERN_INFO "Device opened\n");
          return 0;
      }
      ​
      static const struct file_operations my_fops = {
          .owner = THIS_MODULE,
          .open = drv_open,
          // 其他操作函数
      };

之间的联系和流程

  1. 用户空间调用 open 系统调用

    • 用户空间的应用程序通过调用 open 系统调用请求打开一个文件或设备。

  2. 进入内核空间,调用 syscall_open

    • 系统调用机制将控制权转交给内核,进入 syscall_open 函数(具体名称和实现可能因内核版本不同而有所不同)。

  3. 内核找到对应的文件系统操作方法

    • syscall_open 通过文件路径找到对应的 inode 结构体,从而找到与该文件或设备相关的 struct file_operations 结构体。

  4. 调用驱动程序的 open 方法(drv_open

    • 内核通过 file_operations 结构体中的 open 方法指针,调用具体驱动程序实现的 drv_open 函数。

    • drv_open 执行设备特定的打开操作,如硬件初始化、资源分配等。

函数实现的伪代码

syscall_open函数实现的伪代码:

int syscall_open(const char *filename,int flag)
{
    dev_t devno;
    struct inode *pnode = NULL;
    struct cdev *pcdev = NULL;
    struct file *pfile = NULL;
    int fd = -1;
    
    /*根据filename在内核中查找该文件对应的struct inode对象地址
        找到则pnode指向该对象
        未找到则创建新的struct inode对象,pnode指向该对象,并从文件系统中读取文件的元信息到该对象*/
    if(/*未找到对应的struct inode对象*/)
    {/*根据文件种类决定如何进行下面的操作,如果是字符设备则执行如下操作*/
    
        /*从pnode指向对象中得到设备号*/
        devno = pnode->i_rdev;
    
        /*用devno在字符设备链表查找对应节点,并将该节点的地址赋值给pcdev*/
    
        /*pcdev赋值给pnode的i_cdev成员*/
        pnode->i_cdev = pcdev;
    }
    
    /*创建struct file对象,并将该对象的地址赋值给pfile*/
    
    pfile->f_op = pnode->i_cdev->ops;
    pfile->f_flags = flag;
    
    /*调用驱动程序的open函数*/
    pfile->f_op->open(pnode,pfile,flag);
    
    /*将struct file对象地址填入进程的描述符数组,得到对应位置的下标赋值给fd*/
    
    return fd;
}
  • 18
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值