你好!这里是风筝的博客,

欢迎和我一起交流。


  初入Android,本篇文章不过是拾人牙慧,见笑了~

  init进程,它是内核启动的第一个用户级进程,进程号为1。它通过解析init.rc脚本来构建出系统的初始形态,它的生命周期贯穿整个linux 内核运行的始终。
  核心代码在system/core/init/init.cpp
  程序解读不再累述,可以看这篇文章:Android Init进程源码分析
  大概会做这些事情:
启动守护进程ueventd
设置环境变量
创建一些基本目录,并挂载("/dev", “/dev/pts”,"/dev/pts",,,,)
把标准输入、标准输出和标准错误重定向到空设备文件"/dev/null"
启动kernel log(创建节点/dev/kmsg)
初始化Android的属性系统
解析DT和命令行中的kernel启动参数(dt优先级大于命令行)
设置系统属性
调用selinux_initialize函数启动SELinux
创建epoll,初始化signal(子进程终止信号处理)
加载默认属性,启动属性服务(build.prop等文件)
解析init.rc文件
把rc文件中action加入执行队列中,稍后会启动trigger为"early-init"等的action

  最后init进程会进入一个死循环,在这个无限循环中,init进程会做以下事:
1.执行action_queue列表的action
2.检查系统中是否有进程需要重启
3.处理系统属性变化事件
4.处理子进程的终止(signal方式,会产生SIGCHLD信号发送给init进程),回收僵尸进程。

  其中,在 Android中使用启动脚本init.rc,可以在系统的初始化过程中进行一些简单的初始化操作。这个脚本被直接安装到目标系统的根文件系统中,被 init可执行程序解析。 init.rc是在init启动后被执行的启动脚本
  init.rc的使用方法,可以参考说明文件system/core/init/readme.txt。

  init.rc语法基本由四个部分组成:
Actions、Commands、Services、Options

#这里on 就是一个Actions#write 、restorecon 、start 都是它的Commandson early-init    # Set init and its forked children's oom_adj.    write /proc/1/oom_score_adj -1000    # Set the security context of /adb_keys if present.    restorecon /adb_keys    start ueventd#这里service   [  ]*就是一个Services#class、critical、seclabel 都是它的Optionsservice healthd /sbin/healthd    class core    critical    seclabel u:r:healthd:s0

  每个Actions 和 Services都表示一个新的段落section的开始,所有的commands和options 都是归属于上方最近的一个段落。
  而且每个rc文件里又可以import 导入其他的init.xx.rc文件。

这里试着尝试通过配置init.rc文件实现开机自启动脚本:
脚本实现每次开机后台抓取dmesg写入文本。
修改system/core/rootdir/init.rc:

diff --git a/rootdir/init.rc b/rootdir/init.rc++service kmsg_log /system/bin/kmsg.sh+    class late_start+    seclabel u:r:kmsg_log:s0+ #实测,seclabel 这句很重要,必加

修改device/rockchip/rk3399/device.mk:
拷贝脚本到系统目录中:PRODUCT_COPY_FILES 就是将kmsg.sh文件从源码树中拷贝到镜像文件系统的system/bin路径下

diff --git a/device.mk b/device.mk++PRODUCT_COPY_FILES += \+    device/rockchip/rk3399/kmsg.sh:system/bin/kmsg.sh

编写device/rockchip/rk3399/kmsg.sh:

#!/system/bin/shcount=3for i in `seq $(($count+1))`do    #echo "i is $i"    if [ ! -f "/data/logs/kmsg_$i.log" ]; then        break    fidoneif [ $i -eq $(($count+1)) ]; then    rm /data/logs/kmsg_1.log    i=$count    for j in `seq $(($count-1))`    do        #echo "/data/log/kmsg_$(($j+1)).log /data/log/kmsg_$j.log"        mv /data/logs/kmsg_$(($j+1)).log /data/logs/kmsg_$j.log    donefi#save date, otherwise the date of file will be flushed.date > /data/logs/kmsg_$i.logdmesg >> /data/logs/kmsg_$i.logcat /proc/kmsg >> /data/logs/kmsg_$i.log

脚本参考:[RK3399][Android7.1] 调试笔记 — 开机后台抓取kmsg log
  不过很遗憾,实践时会发现不会成功,有错误:
init: Service kmsg_log does not have a SELinux domain defined.
  这里就涉及一个很重要的东西,就是SELinux!
  这是一种系统安全机制,如果没有在SELinux里给予service对应的权限规则,那么系统是不会让service正常启动的!
  所以我们需要定义一个SELinux domain,添加对应的权限。
  添加device/rockchip/common/sepolicy/kmsg-log.te文件:
  前面几句是SELinux 域的初始模板,可以根据该可执行文件执行的具体操作为该模板添加规则

type kmsg_log, domain;type kmsg_log_exec, exec_type, file_type;type kmsg_log-cnf, file_type;init_daemon_domain(kmsg_log)allow kmsg_log kmsg_log-cnf:file read;allow kmsg_log rootfs:lnk_file getattr;allow kmsg_log kernel:system syslog_read;allow kmsg_log kmsg_device:chr_file { read open };allow kmsg_log kmsg_log-cnf:file { getattr open };

修改device/rockchip/common/sepolicy/file_contexts文件:

diff --git a/sepolicy/file_contexts b//sepolicy/file_contexts++/system/bin/kmsg_log.sh     u:object_r:kmsg_log_exec:s0

  这里就不用修改Android.mk添加te文件了,因为在
system/sepolicysystem/sepolicy/Android.mk文件里条注释:
# Builds paths for all policy files found in BOARD_SEPOLICY_DIRS and the LOCAL_PATH.
  就是说会自动去编译BOARD_SEPOLICY_DIRS路径下的te文件,我们搜索可知,BOARD_SEPOLICY_DIRS就是device/rockchip/common/sepolicy/

  关于SELinux domain的编写,
参考:Android init.rc启动服务
深入理解SELinux SEAndroid(第一部分)
SEAndroid安全机制简要介绍和学习计划

  最后把boot.img和system.img烧写进系统,就可以看到脚本开机自启了。

init.c 、init.rc init.xx.rc 等最终会编译到ramdisk.img(根文件系统)中,和kernel一起打包成boot.img。android启动后每次都会从boot.img中解压出init.c等文件到内存,所以要修改必须修改替换boot.img

  另外:通过getprop | grep init.svc 可查看所有的service运行状态。状态总共分为:running, stopped, restarting
如果文件没有执行权限的话,可以在system/coce/libcutils/fs_config.c文件的android_files[]数组里添加权限

  最后给出一些参数

Triggers说明--------------------------------------------------------------------------------early-init在初始化早期阶段触发late-init在初始化晚期阶段触发init在初始化阶段触发late-init在初始化晚期阶段触发boot/charger当系统启动/充电时触发property:=当属性值满足条件时触发 如:on property:ro.debuggable=1fs挂载mtd分区时触发boot基本网络的初始化,内存管理等时触发post-fs改变系统目录的访问权限时触发device-added-设备节点添加时触发device-removed-设备节点删除时触发service-exited-   在特定服务(service)退出时触发Command说明--------------------------------------------------------------------------------import 导入init.XX.rc、xxx.conf等文件chmod  更改文件访问权限chown   更改文件所有者和组chdir 变更工作目录chroot  改变进程根目录insmod 加载XX.ko驱动模块start 如果服务尚未运行,则启动服务stop 如果当前在运行则停止服务运行class_start 启动指定类的所有服务class_stop 停止指定类的所有服务class_reset 重启指定类的所有服务setprop  设置系统属性< Name >至export   设置全局环境变量,这个变量值可以被所有进程访问(全局的,一直存在)mkdir  [mode] [owner] [group]mkdir  [mode] [owner] [group]创建目录,后面项缺省值为 mode,owner,group: 0755 root roottrigger 触发一个事件。用于将action从另一个action 队列exec  [  ]* 执行指定的Program,并可以带有执行参数,会阻塞initifup 启动某个网络接口,使其为up状态,通过netcfg可以查看,ifup eth0  等价于 netcfg eth0 up 功能一样hostname 设置设备的主机名domainname 设置网络域名localdomainmount    [  ]*把device挂接到dir目录下面,文件系统类型为typewrite   [  ]*打开一个文件,利用write命令写入一个或多个字符串loglevel 设置log级别symlink  创建连接到符号链接Option说明--------------------------------------------------------------------------------class 服务属于class_name这个类。缺省值service属于 “default” 类。同一个class下面的服务可以一起启动或停止disabled 服务不会随class自动启动,要用start server_name 或 property_set("ctl.start", server_name);才能启动oneshot当服务退出后,不会再重新启动,如果没有加这个option,则服务默认退出后又会重新重启user 声明服务的用户名,缺省值应该为root用户group  [  ]*声明服务所属组名,可以一次声明属于多个组onrestart   + command服务重启的时,会执行onrestart后面的commandsetenv  在当前服务进程中设置环境变量name的值为value,环境变量仅在本进程内生效critical声明为设备的循环服务。如果服务在四分钟内退出了四次,则设备会进入recovery模式socket    [  [  ] ] 创建名为/dev/socket/的unix domain socket ,并把它的句柄fd传给本服务进程seclabel 执行服务之前改变安全级别

参考:
android系统启动流程之init.rc详细分析笔记
init.rc内容解析可以看看这个:Android系统init进程启动及init.rc全解析

更多相关文章

  1. NPM 和webpack 的基础使用
  2. 【阿里云镜像】使用阿里巴巴DNS镜像源——DNS配置教程
  3. 读取android手机流量信息
  4. 浅析android通过jni控制service服务程序的简易流程
  5. android 使用html5作布局文件: webview跟javascript交互
  6. Android(安卓)Wifi模块分析(三)
  7. Android(安卓)多媒体扫描过程(Android(安卓)Media Scanner Proces
  8. android“设置”里的版本号
  9. Android开发环境搭建

随机推荐

  1. android应用开发实战
  2. Android多媒体开发(3)————使用Android
  3. android init.rc 分析
  4. android获取短信所有内容
  5. android 8.0 MountService -->StorageMan
  6. Android 8天入门
  7. android studio :com.android.support:app
  8. FileProvider无法获取外置SD卡问题解决方
  9. Eclipse Indigo - Cannot install Androi
  10. Ubuntu 11.04 下搭建Android NDK开发环境