文档中心 > 芯片厂商开放

KDBUS移植

更新时间:2017/08/15 访问次数:5485

文档内容拷贝自:codebase_host/yunhal/opendoc/zh/porting_guide/kdbus.md
联系人:李诚
版本:commit-id(9c70d1039181574402b7af4efa36e3090f0f8d10

变更记录

版本编号 修订内容 日期 修订人
0.1 初稿 2016.06.12 李诚
0.2 针对codebase_host_ocean分支修订 2017.03.15 李诚

1 功能说明

KDBus是D-Bus协议在内核层的实现,作为YunOS的IPC机制为上层应用服务。同时也是YunOS权限系统不可或缺的组成部分。(权限相关内容请参考“权限系统移植文档”)

2 功能移植

2.1 代码移植

KDBus代码来自于上游社区,参考https://github.com/gregkh/kdbus 。最初的KDBus代码是基于Kernel-3.18版本实现,后来跟随Linux Kernel的演进而不断更新,最新的kdbus代码是基于kernel-4.4版本的。

2.1.1 新增代码

YunOS6.0中,KDBus代码位于host/security/extern/gpl/kernel/ipc目录,编译时通过软连接的方式参与kernel的编译。
代码目录结构如下:

security/extern/gpl/kernel/
├── include
│   └── uapi
│       └── linux
│           └── kdbus.h
└── ipc
    └── kdbus
        ├── *.c
        ├── *.h

KDBus代码中采用KERNEL_VERSION宏来包围特定内核版本的API接口,可以同时支持不同版本的内核。

由于KDBus代码最终并未进入Linux主线,所以没有经过大规模验证。随着YunOS在TV,手机和车机等多个平台的长期使用,暴露出一些bug,比如不能给自身connection发消息,给不存在的service发异步消息时不能立即返回错误等等。这些bug在YunOS6.0上都已修复。

此外,YunOS6.0中,KDBus也添加了对debugfs的支持,方便调试。

2.1.2 内核代码修改

为使KDBus在低版本的kernel上可以工作,修改了一些不存在或工作不正常的api接口,如task_cgroup_path(), truncate_inode_pages_final()等,以及struct timespec等结构体。

memfd机制是在Kernel-3.18版本合入linux主线的,若平台所用kernel版本较低,仍需手动移植memfd相关代码。特别注意的是,不同版本的kernel其支持的系统调用总数是不同的,需要为memfd_create()设定合适的系统调用号,并且此系统调用号必须与host/third_party/libkdbus/shared/memfd.h保持一致。

YunOS6.0适配过多个平台,kernel版本有3.10, 3.14, 3.18和4.4等。适配kernel-4.4版本最简单,只需修改init/Kconfig和ipc/Makefile,并参考2.1.3节使能KDBus即可。

而适配kernel-3.10则需要的改动最多,也比较分散。可参考:

http://gerrit2.alibaba-inc.com:8080/#/c/170140
http://gerrit2.alibaba-inc.com:8080/#/c/170141

涉及代码有:

kernel/
├── arch/arm/  或 arch/x86 或arch/arm64 : 添加memfd_create()系统调用号
│
├── fs/*.c  :  主要是反向移植iterate_dir()以及支持memfd的SEAL机制
│
├── include/linux/*.h  : 主要是添加新版本linux的数据结构及API接口
│       └── linux
│           └──*.h
│       └── uapi
│           └── linux
│               └── *.h

├── init/Kconfig  :  添加config KDBUS
│          
├── ipc/Makefile  :  编译 KDBus代码
│          
├── kernel/*.c  :  反向移植必要的API接口
│          
├── lib/*.c  :    反向移植div64和idr相关代码
│          
├── mm/*.c  :    反向移植memfd相关代码
│

2.1.3 KDBus使能

打开CONFIG_KDBUS即可使能KDBus。另外需要在编译host时指定- -with-kdbus=yes。若不写- -with-kdbus,缺省值是yes。

2.1.4 生成文件

打开CONFIG_KDBUS后,KDBus相应代码会编译进内核中。

2.1.5 外部依赖

KDBus本身工作并没有其他依赖,但上层应用不能直接与kernel 中的KDBus交互,所以KDBus在平台上正常工作,需要上层的libkdbus, libbase,ubus.js等文件都存在,且包含完整的patch。

2.1.6 常见问题

? Memfd_create()的系统调用号
由于memfd及相关的系统调用是在3.18及以上的内核版本才存在,在低版本的内核上需要为SYSCALL_memfd选定一个号码,且与third_party/libkdbus/shared/memfd.h中的系统调用号保持一致。

注意:在SC9860等ARM64平台,在上述patch之外,需额外修改
arch/arm64/include/asm/unistd.h
和 arch/arm64/include/asm/unistd32.h
以确保memfd的系统调用号 以及系统总的系统调用数目作了相应修改。

? 系统启动后kdbusfs不能正常挂载
只在L5pro手机平台移植时出现此问题,原因是在L5pro平台打开CONFIG_KDBUS需要同时修改l5pro_debug_defconfig 和 l5pro_defconfig 两个文件,否则CONFIG_KDBUS不生效。

? 系统启动后kdbusfs虽正常挂载,但无法看到/sys/fs/kdbus目录下的文件节点
两个可能原因:一是平台上有host和container两个文件系统,要注意adb/acb连接的是哪个系统,如果连接的是container,要去/root/sys/fs/kdbus目录下去看是否有文件节点。
另一个原因和CONFIG_COMPAT选项有关。为使KDBus在低版本内核上能工作正常,我们修改了fs/readdir.c中的系统调用及相关数据结构体,但在Intel CPU的PAD 平台上,使能了CONFIG_COMPAT选项,所以其真正调用的是fs/compat.c里的系统调用函数。

? 系统启动后桌面黑屏,logcat报“can’t send kdbus method call,… error: invalid argument”
这是由于上层权限相关的代码在平台bringup的过程中已经合入,但KDBus初始移植时权限相关的patch尚未合入,导致上层应用所发的消息中所附带的KDBUS_ITEM_SESSION_PERM部分不被kernel KDBus所识别,所以出错。

3 Checkpoint

BaseTest --gtest_filter=DBusSignalTest.* 
BaseTest --gtest_filter=DBusDeathTest.*
BaseTest --gtest_filter=DBusTest.*
这三个命令需运行正常,以便确保kdbus可以正常工作。

4 移植验证

移植完成后,KDBus能否正常工作,可由多个层面的单元测试来验证。因为KDBus提供给上层应用使用,由下而上经过了libsystemd, libbase, libubus多层封装,每层封装都有自己的单元测试,所有单元测试都通过,才能确保应用基于KDBus的IPC能正常工作。

一是third_party/kdbus_test目录下的单元测试,这是社区提供的单元测试用例,直接测试KDBus kernel代码的。

二是third_party/libkdbus/sd-bus/test-bus*.c编译出的测试用例,确保libkdbus需要KDBus提供的功能都工作正常。

三是framework/libs/base/test/DBus*.cpp编译出的测试用例。

四是framework/npm/extras/node-ubus/test/目录下的JS测试脚本。

5 附录

5.1 参考

Kdbus

FAQ

关于此文档暂时还没有FAQ
返回
顶部