首页 > 其他分享 >ioctl基于接口 【ChatGPT】

ioctl基于接口 【ChatGPT】

时间:2023-12-10 14:33:25浏览次数:49  
标签:compat __ 驱动程序 接口 ioctl 内核 ChatGPT 指针

ioctl基于接口

ioctl()是应用程序与设备驱动程序进行接口交互的最常见方式。它灵活且易于通过添加新命令进行扩展,并且可以通过字符设备、块设备以及套接字和其他特殊文件描述符进行传递。

然而,很容易错误地定义ioctl命令,并且很难在不破坏现有应用程序的情况下修复它们,因此本文档试图帮助开发人员正确使用它。

命令编号定义

命令编号或请求编号是传递给ioctl系统调用的第二个参数。虽然这可以是任何32位数字,用于唯一标识特定驱动程序的操作,但在定义它们时有一些约定。

include/uapi/asm-generic/ioctl.h提供了四个宏,用于定义遵循现代约定的ioctl命令:_IO、_IOR、_IOW和_IOWR。对于所有新命令,应使用这些宏,并使用正确的参数:

  • _IO/_IOR/_IOW/_IOWR

    宏名称指定参数的使用方式。它可以是指向要传递到内核的数据的指针(_IOW),从内核传出的数据的指针(_IOR),或者两者都有的指针(_IOWR)。_IO可以表示没有参数的命令或传递整数值而不是指针的命令。建议仅对没有参数的命令使用_IO,并使用指针传递数据。

  • type

    一个8位数字,通常是特定子系统或驱动程序的字符字面值,并在Ioctl Numbers中列出

  • nr

    一个8位数字,用于标识特定命令,在给定'type'值的情况下是唯一的

  • data_type

    参数指向的数据类型的名称,命令编号将sizeof(data_type)值编码为13位或14位整数,从而限制了参数的最大大小为8191字节。注意:不要将sizeof(data_type)类型传递给_IOR/_IOW/IOWR,因为这将导致编码sizeof(sizeof(data_type)),即sizeof(size_t)。_IO没有data_type参数。

接口版本

某些子系统在数据结构中使用版本号,以重载具有不同参数解释的命令。

这通常是一个不好的做法,因为更改现有命令往往会破坏现有应用程序。

更好的方法是添加一个具有新编号的新ioctl命令。为了兼容性,旧命令仍然需要在内核中实现,但可以将其包装在新实现的周围。

返回代码

ioctl命令可以返回负错误代码,如errno(3)中所述;这些错误代码在用户空间中转换为errno值。成功时,返回代码应为零。也可以返回正的'long'值,但不建议这样做。

当使用未知命令编号调用ioctl回调时,处理程序返回-ENOTTY或-ENOIOCTLCMD,这也导致从系统调用返回-ENOTTY。一些子系统在这里返回-ENOSYS或-EINVAL是出于历史原因,但这是错误的。

在Linux 5.5之前,compat_ioctl处理程序需要返回-ENOIOCTLCMD,以便使用回退转换为本机命令。由于现在所有子系统都负责处理兼容模式,因此不再需要这样做,但在将错误修复移植到旧内核时,考虑到这一点可能很重要。

时间戳

传统上,时间戳和超时值被传递为struct timespec或struct timeval,但由于64位time_t的移动后,这些结构在用户空间中的定义不兼容,因此存在问题。

当需要单独的秒/纳秒值时,可以使用struct __kernel_timespec类型嵌入到其他数据结构中,或直接传递给用户空间。然而,这仍然不是理想的解决方案,因为该结构既不匹配内核的timespec64,也不完全匹配用户空间的timespec。可以使用get_timespec64()和put_timespec64()辅助函数来确保布局与用户空间兼容,并正确处理填充。

由于将秒转换为纳秒很简单,但相反需要昂贵的64位除法,因此简单的__u64纳秒值可能更简单和更高效。

超时值和时间戳应理想地使用CLOCK_MONOTONIC时间,如ktime_get_ns()或ktime_get_ts64()所返回的那样。与CLOCK_REALTIME不同,这使得时间戳免受由于闰秒调整和clock_settime()调用而向前或向后跳动的影响。

对于需要在重启或多台机器之间持久存在的CLOCK_REALTIME时间戳,可以使用ktime_get_real_ns()。

32位兼容模式

为了支持在64位机器上运行的32位用户空间,每个实现ioctl回调处理程序的子系统或驱动程序也必须实现相应的compat_ioctl处理程序。

只要遵循数据结构的所有规则,这很容易,只需将.compat_ioctl指针设置为诸如compat_ptr_ioctl()或blkdev_compat_ptr_ioctl()之类的辅助函数即可。

compat_ptr()

在s390架构上,31位用户空间对于数据指针具有模糊的表示,忽略了最高位。在以compat模式运行此类进程时,必须使用compat_ptr()辅助函数来清除compat_uptr_t的最高位,并将其转换为有效的64位指针。在其他架构上,此宏仅执行到void __user *指针的转换。

在compat_ioctl()回调中,最后一个参数是一个unsigned long,可以根据命令将其解释为指针或标量。如果它是标量,则不能使用compat_ptr(),以确保64位内核对于带有设置了最高位的参数的行为与32位内核相同。

对于仅接受指向兼容数据结构的指针的驱动程序,可以使用compat_ptr_ioctl()辅助函数来替代自定义的compat_ioctl文件操作。

结构布局

兼容的数据结构在所有架构上具有相同的布局,避免了所有问题成员:

  • long和unsigned long的大小与寄存器相同,因此它们可以是32位或64位宽,并且不能用于可移植的数据结构。固定长度的替代类型是__s32、__u32、__s64和__u64。

  • 指针也有同样的问题,除了需要使用compat_ptr()之外。最好的解决方法是在指针的位置使用__u64,这需要在用户空间中进行uintptr_t的转换,并在内核中使用u64_to_user_ptr()将其转换回用户指针。

  • 在x86-32(i386)架构上,64位变量的对齐方式只有32位,但在包括x86-64在内的大多数其他架构上,它们是自然对齐的。这意味着在x86-64上,像这样的结构:

    struct foo {
        __u32 a;
        __u64 b;
        __u32 c;
    };
    

    在a和b之间有4个字节的填充,在结尾处还有另外4个字节的填充,但在i386上没有填充,并且它需要一个compat_ioctl转换处理程序来在这两种格式之间进行转换。

  • 为了避免这个问题,所有的结构都应该有自然对齐的成员,或者在隐式填充的位置添加显式保留字段。可以使用pahole工具来检查对齐情况。

  • 在ARM OABI用户空间,结构被填充到32位的倍数,如果它们不以32位边界结束,这会导致一些结构与现代EABI内核不兼容。

  • 在m68k架构上,结构成员不能保证具有大于16位的对齐方式,这在依赖隐式填充时会成为一个问题。

  • 位字段和枚举通常按照预期工作,但它们的一些属性是实现定义的,因此最好完全避免在ioctl接口中使用它们。

  • char成员可以是有符号的或无符号的,这取决于架构,因此应该使用__u8和__s8类型来表示8位整数值,尽管对于固定长度的字符串,使用char数组更清晰。

信息泄漏

未初始化的数据不能被复制回用户空间,因为这可能导致信息泄漏,从而可以用来破解内核地址空间布局随机化(KASLR),从而帮助攻击。

因此(并且为了兼容性支持),最好避免数据结构中的任何隐式填充。在现有结构中存在隐式填充的情况下,内核驱动程序必须小心地在将结构的实例复制到用户空间之前完全初始化该结构的实例。通常在分配给各个成员之前调用memset()来完成这个操作。

子系统抽象

虽然一些设备驱动程序实现了自己的ioctl函数,但大多数子系统为多个驱动程序实现了相同的命令。理想情况下,子系统具有一个.ioctl()处理程序,它将参数从用户空间复制到子系统特定的回调函数中,通过正常的内核指针传递给它们。

这有助于解决以下问题:

  • 如果用户空间ABI没有微妙的差异,那么为一个驱动程序编写的应用程序更有可能适用于同一子系统中的另一个驱动程序。

  • 用户空间访问和数据结构布局的复杂性在一个地方完成,减少了实现错误的可能性。

  • 当ioctl在多个驱动程序之间共享时,有经验的开发人员更有可能对接口中的问题进行审查,而当它仅在单个驱动程序中使用时则不太可能。

ioctl的替代方案

有许多情况下,ioctl并不是解决问题的最佳方案。替代方案包括:

  • 系统调用是一个更好的选择,用于不与物理设备绑定或受字符设备节点的文件系统权限限制的系统范围功能。

  • netlink是通过套接字配置任何与网络相关的对象的首选方式。

  • debugfs用于调试功能的临时接口,不需要将其作为稳定接口暴露给应用程序。

  • sysfs是一种很好的方式,用于公开与文件描述符无关的内核对象的状态。

  • configfs可用于比sysfs更复杂的配置。

  • 自定义文件系统可以提供简单的用户界面,但会给实现带来很多复杂性。

标签:compat,__,驱动程序,接口,ioctl,内核,ChatGPT,指针
From: https://www.cnblogs.com/pengdonglin137/p/17892620.html

相关文章

  • 将驱动程序移植到新的驱动模型 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/driver-api/driver-model/porting.html将驱动程序移植到新的驱动模型PatrickMochel2003年1月7日概述请参阅Documentation/driver-api/driver-model/*.rst以获取各种驱动程序类型和概念的定义。将设备驱动程序移植到新模型的大部分......
  • 平台设备和驱动程序 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/driver-api/driver-model/platform.html平台设备和驱动程序请参阅<linux/platform_device.h>以获取与平台总线的驱动程序模型接口相关的信息:platform_device和platform_driver。这个伪总线用于连接具有最小基础设施的总线上的设备,例如用......
  • 设备驱动程序 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/driver-api/driver-model/driver.html设备驱动程序请参阅结构体device_driver的kerneldoc。分配设备驱动程序是静态分配的结构。尽管系统中可能有多个驱动程序支持的设备,但structdevice_driver代表了整个驱动程序(而不是特定的设备实......
  • 总线类型 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/driver-api/driver-model/bus.html总线类型定义请参阅结构体bus_type的内核文档。intbus_register(structbus_type*bus);声明内核中的每个总线类型(如PCI、USB等)应该声明一个此类型的静态对象。它们必须初始化name字段,并可以选......
  • 设备驱动设计模式 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/driver-api/driver-model/design-patterns.html设备驱动设计模式这份文档描述了设备驱动中常见的设计模式。子系统维护者可能会要求驱动开发者遵循这些设计模式。状态容器container_of()1.状态容器虽然内核中包含一些设备驱动,假......
  • 设备基本结构 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/driver-api/driver-model/device.html设备基本结构请参阅内核文档以了解structdevice的结构。编程接口发现设备的总线驱动程序使用以下方法将设备注册到核心:intdevice_register(structdevice*dev);总线应该初始化以下字段:p......
  • Devres - 管理设备资源 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/driver-api/driver-model/devres.htmlDevres-管理设备资源[email protected]首稿日期:2007年1月10日1.简介在尝试将libata转换为使用iomap时,出现了devres。每个iomapped地址应该在驱动程序分离时保留和取消映射。例如,一个普......
  • 驱动绑定 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/driver-api/driver-model/binding.html驱动绑定驱动绑定是将设备与能够控制它的设备驱动程序关联起来的过程。通常由总线驱动程序处理这一过程,因为总线特定的结构用于表示设备和驱动程序。使用通用设备和设备驱动程序结构后,大部分绑定可......
  • 硬件自旋锁框架 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/locking/hwspinlock.html硬件自旋锁框架简介硬件自旋锁模块为异构处理器和不在单一共享操作系统下运行的处理器之间的同步和互斥提供硬件辅助。例如,OMAP4具有双核Cortex-A9、双核Cortex-M3和一个C64x+DSP,每个处理器运行不同的操作系......
  • 驱动模型 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/driver-api/driver-model/index.htmlDriverModel(驱动程序模型)DriverBinding(驱动绑定)BusTypes(总线类型)DeviceDriverDesignPatterns(设备驱动程序设计模式)TheBasicDeviceStructure(基本设备结构)Devres-ManagedDeviceResou......