Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1710643
  • 博文数量: 143
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1462
  • 用 户 组: 普通用户
  • 注册时间: 2016-08-23 11:14
文章分类

全部博文(143)

文章存档

2022年(3)

2021年(13)

2020年(21)

2019年(8)

2018年(28)

2017年(7)

2016年(63)

我的朋友

分类: LINUX

2018-11-11 21:49:23

简介:本文目的是搞清楚①filp->f_op->ioctl是如何指向字符设备ioctl;或者socket控制ioctl。以及标准socket控制ioctl中②sock->ops->ioctl是如何指向inet_ioctl的。(虽然我已清楚如何写,但双11到现在还没吃饭,先把所要参考的帖子附上并附上关健部分,后面再梳理和排版吧~.~...
  显然,使用ioctl()前,fd或用open()打开,或用socket()打开。
  驱动程序运行于内核空间,用户空间的应用程序通过文件系统中/dev/目录下的一个文件来和它交互。这就是我们熟悉的那个文件操作流程:open() —— read() —— write() ——ioctl() ——close()。(需要注意的是也不是所有的内核驱动程序都是这个界面,网络驱动程序和各种协议栈的使用就不大一致,比如说“套接口编程”虽然也有open()close()等概念,但它的内核实现以及外部使用方式都和普通驱动程序有很大差异。)
  使用ioctl系统调用是用户空间向内核交换数据的常用方法之一,从ioctl这个名称上看,本意是针对I/O设备进行的控制操作,但实际并不限制是真正的I/O设备,可以是任何一个内核设备即可。在内核空间中ioctl是很多内核操作结构的一个成员函数,如文件操作结构struct file_operations(include/linux/fs.h)、协议操作结构struct proto_ops(include/linux/net.h)等、tty操作结构struct tty_driver(include/linux/tty_driver.h)等,而这些操作结构分别对应各种内核设备,只要在用户空间打开这些设备, 如I/O设备可用open(2)打开,网络协议可用socket(2)打开等,获取一个文件描述符后,就可以在这个描述符上调用ioctl(2)来向内核交换数据。
一、字符设备ioctl
1.filp->f_op->ioctl是如何指向spidev_ioctl的--->open()
参考:Linux设备文件三大结构:inode,file,file_operations  以及其中指向的另一篇帖子。
  Linux内核会为每一个进程维护一个文件描述符表,这个表其实就是struct file[]的索引。open()的过程其实就是根据传入的路径填充好一个file结构并将其赋值到数组中并返回其索引。

点击(此处)折叠或打开

  1. chrdev_open()
  2. --352-389-->利用container_of等根据inode中的成员找到相应的cdev
  3. --390-->用cdev.fops替换filp->f_op,即填充了一个空的struct file的f_op成员。
  4. --392-->回调替换之后的filp->f_op->open,由于替换,这个其实就是cdev.fops


  首先,在一个字符设备文件被创建的时候,内核会构造相应的inode。
  由此可见,对一个字符设备的访问流程大概是:文件路径=>inode=>chrdev_open()=>(kobj_lookup=>)inode.i_cdev=>cdev.fops.my_chr_open()。所以只要通过VFS找到了inode,就可以找到chrdev_open(),这里我们就来关注一个chrdev_open()是怎么从内核的数据结构中找到我们的cdev并执行其中的my_chr_open()的。比较有意思的是,虽然我们有了字符设备的设备文件,inode也被构造并初始化了, 但是在第一次调用chrdev_open()之前,这个inode和具体的chr_dev对象并没有直接关系,而只是通过设备号建立的"间接"关系。在第一次调用chrdev_open()之后, inode->i_cdev才被根据设备号找到的cdev对象赋值,此后inode才和具体的cdev对象直接联系在了一起。

点击(此处)折叠或打开

  1. chrdev_open()
  2. --359-->尝试将inode->i_cdev(一个cdev结构指针)保存在局部变量p中,
  3. --360-->如果p为空,即inode->i_cdev为空,
  4. --364-->我们就根据inode->i_rdev(设备号)通过kobj_lookup()搜索cdev_map,并返回与之对应kobj,
  5. --367-->由于kobject是cdev的父类,我们根据container_of很容易找到相应的cdev结构并将其保存在inode->i_cdev中
  6. --374-->找到了cdev,我们就可以将inode->devices挂接到inode->i_cdev的管理链表中,这样下次就不用重新搜索,
  7. --378-->直接cdev_get()即可。
  8. --386-->找到了我们的cdev结构,我们就可以将其中的操作方法集inode->i_cdev->ops传递给filp->f_ops(386-390)
  9. --392-->这样,我们就可以回调我们的设备打开函数my_chr_open();如果我们没有实现自己的open接口,就什么都不做,也不是错

二、socket控制ioctl
2.filp->f_op->ioctl是如何指向sock_ioctl的--->socket()
参考:linux网络协议栈分析——ioctl的调用流程  linux内核与用户之间的通信方式——虚拟文件系统、ioctl以及netlink

2.1.标准socket控制ioctl中,sock->ops->ioctl是如何指向inet_ioctl的
参考:同上2个。

阅读(4529) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~