HDF用户态和内核态之间是怎样调用的? 原创 精华
有兄弟在gitee的OpenHarmony/drivers_framework仓库提issue,见“HDF用户态和内核态之间是怎样调用的?”
我看到了就做了简单回答如下,对鸿蒙驱动开发感兴趣或者有疑问的朋友,建议去gitee看原问答和其它相关issue的问答。
在标准系统中,HDF分用户态和内核态两部分,如何快速确定某个源文件是工作在用户态还是内核态?
可以搜索文件名,使用BUILD.gn构建成so的,是工作在用户态,使用Makefile构建的,是在内核态。
注意有部分文件是用户态和内核态共用的。
用户态驱动是以so库的形式存在吗?由哪个程序去负责加载这些so库,并将其注册到系统中?
drivers\adapter\uhdf2\host\src\driver_loader_full.c 的 HdfDriverLoaderGetDriverEntry()函数中,会通过两个strcat_s操作,拼接出用户态驱动so库的部署路径和库名,如:/system/lib/libsample_driver.z.so,通过realpath/dlopen/dlsym 来获取用户态驱动的入口 HdfDriverEntry,接下来就按流程执行其中的Bind/Init函数。
这个开发模型是否有详细的文档、框图等资料提供?
我已经完成了几乎整个HDF的详细分析,画出了详细的流程图和各模块之间的关系图,请关注即将出版的南向开发书籍《鸿蒙系统学习笔记》。
用户态驱动是如何注册到系统中的?
通过部署在用户态的hcs文件描述驱动配置信息,见//vendor/hisilicon/Hi3516DV300/hdf_config/uhdf/*.hcs
因为用户态驱动都是以动态库方式部署的,并且只对用户态提供服务,所以它的policy都是2,moduleName就是对应的动态库的全名。
编译和分析hcs/hcb文件,仍是hc-gen/hcs-parser。
解析hcb文件的过程和结果,见//drivers/adapter/uhdf2/manager/src/hdf_get_attribute.c内相关函数。
用户态驱动的so库如何告诉加载器自己是一个用户态驱动呢?
在//vendor/hisilicon/Hi3516DV300/hdf_config/uhdf/*.hcs里配置的驱动,都是用户态驱动,
一个用户态驱动是否能且仅能对外暴露一个driverDesc?
目前看起来是这样的,我有九成把握给肯定答案,但最好是官方确认一下。
用户态驱动的so库代码是运行在哪个进程上下文中?
所有用户态驱动的so库是运行在同一个进程上下文中吗?
hdf_devmgr进程是用户态设备驱动管理者进程,它不直接运行用户态驱动so库,它为每一个host fork一个子进程,每个子进程独立运行对应的host的so库,如sample_host进程运行libsample_driver.z.so
设备对象是由谁提供的?
每个设备驱动在执行自己的Bind/Init相关流程中,会生成DeviceServiceStub对象,里面会包含对应的HdfDeviceObject ,见HdfDriverLoaderLoadNode()内的操作。
调用逻辑大概如下。。。。但是这个逻辑是怎么开始的?后面又是如何通知到内核进行块设备注册的?
调用过程,有若干次hdf_devmgr进程和具体host进程之间的跨进程交互,你的逻辑还不完全准确。
我的书籍里给出了完整的交互过程和流程图,敬请关注。
用户态驱动不需要到内核进行注册,它对应用提供HDI接口,再通过系统调用进入内核态,使用内核态驱动提供的服务。
一个应用调用gralloc函数的流程。。。。。
display驱动模型我没有深入分析,但我深入分析了wlan驱动模型,相关流程估计可做参考,也请关注《鸿蒙系统学习笔记》这本书.
感谢,文章解决了很多疑惑
你好,这些问题还是没有解答用户态怎么调用内核态的。
uhdf是用户态的驱动,和内核无关。
khdf是内核态的驱动,请问,内核态的设备管理服务是怎么向外提供服务的、内核态驱动是怎么注册、启动的?用户态怎么调用内核驱动的接口
你这几个问题比较大,三言两语还真说不清楚,不过在我的书里都有了非常详细的说明,并且有对应的数据结构关系图,到时候你对着图一看就明白了。这本书很快就可以和大家见面了。
不用很详细,提供一些关键的函数也可以,我至少可以自己跟代码。
我大概理了一下,khdf的devmgr通过late_initcall初始化,初始化过程会通过注册设备块向用户态开放一些能力(包括devmgr和dev_svc_mgr的能力)。
我有两个疑惑:
1. 但是hkdf里面的驱动,我看也是调的HDF_INIT来初始化的,这个不是用户态用的么,它的功能是把驱动entry地址写到.hdf.driver段,用户态devmgr启动的时候就会初始化并注册这个驱动。难道内核的驱动也是通过用户态的devgmr注册?
2. 用户态进程我只知道可以通过上面说的devmgr设备块和内核交互。但是开放的接口好像没有看到获取内核驱动服务的。我想知道内核驱动服务是自己注册新的设备块来向用户态开放,还是通过内核的devmgr或者dev_svc_mgr
1. “hkdf里面的驱动,我看也是调的HDF_INIT来初始化的,这个不是用户态用的么”
//drivers/adapter/khdf/目录下,全部是编译到内核中的驱动,
//drivers/adapter/uhdf/目录下,是小型系统的用户态驱动框架
//drivers/adapter/uhdf2/目录下,是标准系统的用户态驱动框架
内核态的各驱动,HDF_INIT->HDF_DRIVER_INIT->//drivers/framework/core/common/include/host/hdf_device_section.h
是会编译到内核的.hdf.driver段,然后大概如你所理解的方式启动。
用户态的各驱动,HDF_INIT->HDF_DRIVER_INIT->//drivers/adapter/uhdf2/include/host/hdf_device_section.h
会在用户空间以另外一种截然不同的方式启动。
不管是内核态驱动,还是用户态驱动,DeviceManager 和 DeviceServiceManager 都会以非常重要的、但又不同的形式出现并起关键作用。这中间涉及到了内核态驱动和用户态驱动的代码共用、函数指针分别指向不同的函数、各自结构体(类)的重新定义等等非常容易引起混淆的东西,所以驱动框架的架构还是挺难以让人理解的。
2. 用户态进程我只知道可以通过上面说的devmgr设备块和内核交互。
用户态与内核态的交互,简单来说就是消息机制,更进一步就是系统调用,就是linux的open/ioctl这一套。
具体入口可以认为只有两个:
struct HdfIoService *serv = HdfIoServiceBind(SERVICE_NAME);
serv->dispatcher->Dispatch(struct HdfObject *service, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply);
你可参考《RK3568三色灯点灯流程》中给的示例程序:led_rgb 的调用流程跑一下看看。
如果涉及到用户态进程与用户态进程之间的IPC,那就是另外的故事了。
感谢感谢,我大致明白了!
这个在 代码目录下, ls -la 就会发现,代码是 软链接到 kernel目录下,编译到内核中,
至于对外的使用,跟 其他的 device设备没有本质区别, 还是 文件节点。
不过,我也没太看明白,他搞一个什么 section 段的,就是为存放 鸿蒙搞的一堆hdf 变量,
不知道是 为了解决什么问题