背景
由于Linux 系统分为了用户态和内核态,用户态在设计初衷就是运行与硬件无关的应用程序,与硬件相关的操作大部分都集中在内核态处理。所以用户态如果需要获取硬件信息,或者操作硬件,必须要通过某种方式与内核态进行通信才能得到信息,或者将配置真正下发到硬件上。
本文只描述3种常见的交互方式基本原理和优缺点,并不会详细描述每种方式的具体实现做详细描述,详细的描述开发者可以自行搜索,网上资料不少。
Netlink
Netlink套接字是用以实现用户进程与内核进程通信的一种特殊的进程间通信(IPC) ,也是应用程序与内核通信的最常用的接口方式之一。
优势:
1、 基于套接字方式,对于熟悉网络编程的开发者来说相对简单,内核态代码也只需要做简单初始化就能完成通信。
2、 用户态可以使用epoll 形式,不过多占用CPU资源
限制:
1、Netlink 目前只支持32个通道,其中内核自己就用了20个通道左右,也就是剩余通道数有限,不能复用。
2、对于网络编程不熟悉的开发者,如果这个通信过程中出问题,或者出现丢包,但是应用中不允许出现丢包问题时,比较难定位
3、仅限于通信,如果需要操作硬件还需要在内核态代码中增加相应处理
UIO
UIO主要包含两个功能:一是映射物理内存空间到用户态,使用户态程序能直接操作硬件寄存器或者部分内核申请的内存;另一个是通过设备状态的变化通知用户态程序有中断产生。
优势:
1、 用户态程序能感知到中断状态
2、 用户态程序可以直接操作内存或者寄存器
3、 可以通过直接操作内存进行交互,少了拷贝的动作,效率较高
劣势:
1、相对于netlink来说内核代码稍微复杂一些,涉及到一些中断处理以及设备创建
2、一个UIO设备只能映射4个地址,如果设备的寄存器多且地址分散,可能需要开多个UIO设备才能满足操作需求。
3、如果通过内存方式交互,竞争处理方式比较复杂,需要开发者用户态和内核态程序操作同一份内存,而不会相互覆盖与竞争。
IOCTL
Ioctl 是内核比较早的一种用户态内核态的交互方式,用户态程序通过命令的方式调用ioctl函数,然后内核态分发到对应驱动处理,最后将处理结果返回到用户态。
优势:
1、IOCTL支持的版本较多,资料非常详细
2、用户态编码简单
劣势:
1、 IOCTL由于支持的版本较老,新内核有可能不再支持
2、 IOCTL内核态是根据传入的cmd命令字来解析,如果涉及到多个命令需要编写多个函数,代码量相对较多
3、 相对于内存交互,IOCTL需要解析命令字,才能跳转对应处理函数,同时也有拷贝动作
效率较低
其他自定义方式
目前笔者想到的一种简单的交互方式跟UIO的MEM交互基本一致,需要开发者设计一套内存交互机制,但UIO相对较复杂,需要内核支持,如果只需要MEM交互,只需要自己创建一个设备,在用户态映射这个设备空间就能达到效果。
优势:
1、不需要内核支持UIO,只需要驱动自己创建设备
2、 通过直接操作内存进行交互,少了拷贝的动作,效率较高
3、自己设计,可以自行定义自己的DFX,方便调试
劣势:
1、用户态不能感知中断
2、开发者需要设计一套内存交互机制,而不会相互覆盖与竞争,比较复杂。
————————————————
版权声明:本文为CSDN博主「树非树」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_31796803/article/details/112013721