记自己搭配的linux kernel (4.14)和ASOP(8.1)BINDER适配的问题

本以为选择一个较近代的kernel适配问题会少一些,但是这样自己的配方结果就是没有任何资料可查。

经过此一役,更加深刻的理解了 

Talk is cheap, Show me the code.

程序员一切考代码说话,你看再多别人胡扯都没有。

 

记一下过程:

自己编译的kernel,之前也记录了这个kernel怎么适配的android的选项。

自己看网上下载和编译kernel的blog,跟着编译了一下。

问题也出了好多,都是看网上的解决的,为什么能较快的解决,也是这部分没有涉及到什么具体的代码,前人在这里掉坑的也比较多。

编译出来的android是跑在虚拟机 ranchu上的,但是我也不会改,就直接拿来,硬着头皮往上搞啊。

之前也说过我用的是am335的开发板,内核用的是oampplus的配置,很幸运的是内核能引导。

搞上去之后遇到的第一个大问题就是sepolicy,ASOP给ranchu虚拟机编译的ramdisk.img里没有,这里很纳闷的是为什么它能跑起来,到了我这里就是个坎。

之前对selinux的认知仅限于看到过这个单词,任何的接触和实操都没有过。

接下来就是一顿海量baidu google,看一些概念介绍。但都是模糊的,实操起来还是不行。

因为我是直接用的sdcard装载的rootfs 和system 和vendor,就是直接都放一起了。标准的android这些都是分开的,ramdisk.img应该是和kernel编译在一起的。而我的时间就是拖延在这个上,sdcard和它的.img还是不同的。因为我是把它的*.img里的那些文件拷贝到sdcard的。

一开始没有注意这个selinux的问题,所以内核引导到init就over。然后开启内核的selinux

selinux=1

因为虽然内核选项选择了编译selinux部分,但是默认是不开启这个功能的。也有选项在编译时开启,但是上面这个内核参数也是一个方便的开启的手段。

selinux模块使用之后的问题就是 sepolicy。这在根文件系统里的文件是android的安全策略编译之后的一个文件,它要在init的流程中传给内核,通过selinux/load。内核加载这个文件之后安全系统就起作用了,然后就引发各种权限问题。因为之前的拷贝是直接从target/generic/下面的文件里拷贝过来的,这是各个文件都没有selinux标签,就是 “label”,所以init在访问plat_file_context是总是提示“unlabeld”。就这问题搞了好几天啊o(╥﹏╥)o.

后来看了一下system.img这个镜像中的文件,很神奇,这里的文件竟然都是有标签的。所以就在想编译过程中是怎么把标签打上的,我的ubuntu环境也没有selinux。又是一顿搜o(╥﹏╥)o

没有找到我想看到的,就折中一下把这个system.img 挂载上,把东西拷贝出来。vendor.img同样的操作。

然而在rootfs中 acct文件夹也是要权限控制的,但是ramdisk.img中的文件没有标签。我现在怀疑这个压缩包还缺少点步骤才能使用。然后又是一顿搜,找咱们打标签。但是没有找到能用的。然后就是灵机一动,折中一下,看system.img这个镜像中的文件是怎么弄得吧,但是ASOP这个东西真是好强大,太TM复杂了,看不懂o(╥﹏╥)o。看网上说是用 make4fs这个工具做的,折后就是用这个东西先将rootdisk中的东西做个有标签的镜像,然后再拷贝出来。

然后这个问题暂时解决,继续接着init的流程。

然后就是servicemanager这个native服务老是被kill,反正从串口上看到的就是这个现象

Sending signal 9 to service 'servicemanager'

一直想不明白,为什么就被杀死了呢,他做了什么违法的事?

因为我的开发板资源有限,想是不是内存不足了。但是也不是,init才刚起来能占多大的内存,早些年的入门级也是资源很有限。所以不是资源的问题。

然后一顿搜,无果。

没有任何这个问题的资料。也有说总是退出是因为内核的binder选项没有选好,这个时候纯属误导,我都选了。没有任何卵用,我想着多开一些内核打印看看没有什么东西能看明白。然后想着自己看源码吧,但是对init启动子进程也不是很明白。直接去看了servicemanager的源码,没看出来啥,看着是能出错的都有日志,也没看到啥日志就直接被杀了,这是为什么呢(´⊙ω⊙`)。

在它的源码中加printf 不管用,用它的错误日志也不管用,没有看到任何的输出,就明白过来是这个程序的日志不知道打到那个鬼地方去了,可能是logcat。编译了几次试了下,没有看到东西。因为我的调试手段只有串口,因为资金问题,没有配显示屏。o(╯□╰)o

然后搜init怎么启动的子进程,子进程的输出到哪里了?

然,无果。。。。。。

只能自己看源码

在 system/core/init/service.cpp中有这么一段

bool Service::Start() {
    // Starting a service removes it from the disabled or reset state and
    // immediately takes it out of the restarting state if it was in there.
    flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));

    // Running processes require no additional work --- if they're in the
    // process of exiting, we've ensured that they will immediately restart
    // on exit, unless they are ONESHOT.
    if (flags_ & SVC_RUNNING) {
        return false;
    }

    bool needs_console = (flags_ & SVC_CONSOLE);
    if (needs_console) {
        if (console_.empty()) {
            console_ = default_console;
        }

        // Make sure that open call succeeds to ensure a console driver is
        // properly registered for the device node
        int console_fd = open(console_.c_str(), O_RDWR | O_CLOEXEC);
        if (console_fd < 0) {
            PLOG(ERROR) << "service '" << name_ << "' couldn't open console '" << console_ << "'";
            flags_ |= SVC_DISABLED;
            return false;
        }
        close(console_fd);
    }
    ......
}

其中

bool needs_console = (flags_ & SVC_CONSOLE);

这一行 ,看着最来感,想着终于TM找到了

不断三七二十一,直接给他来成 true,管他什么标志运算,我就死要日志

然而没有那么简单,这一段是对所有的子进程的,我也懒得过滤。所以在init启动第一个子进程时没有

/dev/console

这个设备文件,所有打不开,所以所有子进程直接over,都没给启动的机会。O(∩_∩)O哈哈~

所以要在init的初始化流程手动创建console

mknod("/dev/console", S_IFCHR | 0600, makedev(5, 1));

然后编译运行,我滴个神仙奶奶啊,终于看到了servicemanager的输出。

然后看到原因是binder打不开,所以servicemanager自己退出了,被init擦了屁股

为什么打不开呢?

因为BINDER_VERSION没对上,多不应该的问题啊,就因为自己是菜鸟。

binder: kernel driver version (8) differs from user space version (7)

然后看这个东西是因为

'''在这里我要狂笑三声 哈 哈 哈 , 因为昨天写到这个TM的停电了,写了两个小时的东西,害的我担惊受怕一晚上,早上7点来的点,也没管,刚才看到竟然还在。感谢上帝 如来佛祖。以后一定要养成随手保存的习惯''

因为啥呢?没思路了。

因为 BINDER_CURRENT_PROTOCOL_VERSION 这个宏的定义 AOSP和kernel使用的值没有对上

在内核include/uapi/linux/android/binder.h中有这么一段

/* This is the current protocol version. */
#ifdef BINDER_IPC_32BIT
#define BINDER_CURRENT_PROTOCOL_VERSION 7
#else
#define BINDER_CURRENT_PROTOCOL_VERSION 8
#endif

这个 “BINDER_IPC_32BIT” 在编译kernel的时候是没有定义的,而对于32位arm来说,确实应该要定义。

所以在编译kernel的时候将这个给定义上,重新编译。确实servicemanager不在跑死了。该问题就此解决。

 

以上是这段时间以来面临的两个主要的问题。然后接下来还有很长 很长 很长的路。ヾ(ToT)Bye~Bye~

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值