#############################################
本文为极度寒冰原创,转载请注明出处
#############################################
init进程是android启动过程中的第一个进程,如果我们用adb shell进入到android 手机后,使用ps命令去看android的系统进程的话,会得到如下的结果:
[email protected]:/ # psUSER PID PPID VSIZE RSS WCHAN PC NAMEroot 1 0 748 496 c012d008 000221c8 S /initroot 2 0 0 0 c0088e58 00000000 S kthreaddroot 3 2 0 0 c00727dc 00000000 S ksoftirqd/0root 6 2 0 0 c00b63bc 00000000 S migration/0root 16 2 0 0 c008451c 00000000 S khelperroot 17 2 0 0 c008451c 00000000 S suspend_sys_syn我们可以看到,init进程的pid是,也就是说android启动的第一个进程即为init。
另外,我们看到并不是所有的进程都是由pid=1的进程fork出来的,这个是为什么呢?
这是因为,kthreadd是内核运行的一个进程,主要负责内核态的程序的fork,而我们的Init呢?是负责用户态的应用程序的fork。
再举个例子,
root 195 1 1469220 53940 ffffffff b6ecd97c S zygotenobody 196 1 10624 684 ffffffff b6f4697c S /system/bin/sensors.qcommedia_rw 197 1 3596 336 ffffffff b6f35d58 S /system/bin/sdcardcamera 198 1 4128 1524 ffffffff b6f31384 S /system/bin/mm-qcamera-daemonroot 229 2 0 0 c00b7084 00000000 S kauditdroot 238 173 4920 504 ffffffff b6ed1d38 S /system/bin/qseecomdroot 546 1 4616 220 ffffffff 000218c0 S /sbin/adbdsystem 555 195 1613492 81596 ffffffff b6ecdbfc S system_serversystem 590 172 1740 560 c006f888 b6f70914 S /system/bin/efsksroot 591 2 0 0 c008451c 00000000 S ehci_wqroot 592 2 0 0 c00c1128 00000000 S irq/337-hsic_pesystem 614 590 3568 2360 c03ed33c b6eced58 S /system/bin/ksu0_a14 682 195 1550120 72432 ffffffff b6ecdbfc S com.android.systemuiu0_a5 702 195 1484264 39460 ffffffff b6ecdbfc S android.process.mediau0_a42 835 195 1505696 40396 ffffffff b6ecdbfc S com.android.phasebeamu0_a34 857 195 1495540 41812 ffffffff b6ecdbfc S com.android.inputmethod.latinradio 901 195 1479556 34540 ffffffff b6ecdbfc S com.android.server.telecomnfc 922 195 1498584 38004 ffffffff b6ecdbfc S com.android.nfcradio 959 195 1501608 46188 ffffffff b6ecdbfc S com.android.phone我们可以从这个例子中看到,com.android.systemUI是由PPID为195的进程所孵化的。
而进程号为195的进程为
下面我们就进入到init进程的实现来一探究竟。
root 195 1 1469220 53940 ffffffff b6ecd97c S zygote
zygote的PPID为PID=1的进程,也就是说,是由init进程启动的。
由这个例子也可以看出,android的ap端的万物之祖为init进程。
首先进入到system/core/init下面来看一下目录结构:
.├── Android.mk├── bootchart.c├── bootchart.h├── builtins.c├── devices.c├── devices.h├── grab-bootchart.sh├── init.c├── init.h├── init_parser.c├── init_parser.h├── keychords.c├── keychords.h├── keywords.h├── log.h├── MODULE_LICENSE_APACHE2├── NOTICE├── parser.c├── parser.h├── property_service.c├── property_service.h├── README.BOOTCHART├── readme.txt├── signal_handler.c├── signal_handler.h├── ueventd.c├── ueventd.h├── ueventd_keywords.h├── ueventd_parser.c├── ueventd_parser.h├── util.c├── util.h├── watchdogd.c└── watchdogd.h可以看到init进程,是由c语言实现的,而看C语言的执行,首先要找到main函数。
在我们的这个里面,无疑就是init.c的main函数了。
另外,这里提醒一下,如果我们想要打Log去debug init的话,可以直接使用ERROR()函数来输出LOg
查看的话,直接adb shell cat /proc/kmsg就可以看到init进程中的输出了。
而如果想要编译init进程的话,比较快捷的一个办法是直接在android的source目录下,执行make bootimage去编译出boot.img
然后fastboot flash boot boot.img即可完成boot的烧写,重启打印Log即可~
接下来,我们来一起分析init的main函数。并且一起来分析下为什么adb shell cat /proc/kmsg就可以打印出来Log了?