init进程调试
来自个人维基
调试的原因很简单,就是出现问题了:把一个进程的启动顺序提前,但实际却启动不起来,如:
on fs_property:ro.mount.fs=EXT4 start my_daemon on init start my_daemon
于是要想办法把log打印出来。但在开机前期,log系统、文件系统都还未就绪,因此这不是一个简单的事情。
于是想先把log打印到一个buffer中,待系统启动后再通过通用的log系统打印出来:
#define MAX_LEN (1024*1024*10) char g_kBuffer[MAX_LEN] = {"head\n"}; int g_occupiedByte = 5; void logToBuffer(char *format, ... ) { char *m_str = g_kBuffer+g_occupiedByte; va_list arg_ptr; va_start(arg_ptr, format); vsnprintf(m_str, MAX_LEN-g_occupiedByte-1, format, arg_ptr); //vsprintf va_end(arg_ptr); if(g_kBuffer[strlen(g_kBuffer)-1] != '\n') { strncat(g_kBuffer, "\n", MAX_LEN); } g_occupiedByte = strlen(g_kBuffer); } //受log系统打印长度限制,需分段打印 void printKBuffer() { #define KLOG_MAX_LEN 300 int i = 0; char tmpStr[KLOG_MAX_LEN]; for(i = 0; i < strlen(g_kBuffer);) { strncpy(tmpStr, (char*)(g_kBuffer+i), KLOG_MAX_LEN); klog_write(1, "logyfish>|%s\n", tmpStr); i+=KLOG_MAX_LEN; } } void* logDaemonTrd(void *ptr) { //sleep(20); while(1) { klog_write(1, "\n======================logyfish start=========================\n"); printKBuffer();//klog_write(1, ">|%s\n", g_kBuffer); klog_write(1, "\n======================logyfish end=========================\n"); sleep(3); } return NULL; }
然后再在init的main中启动一个线程用来打印log:
//start:logyfish pthread_t ssdTrd = 0; pthread_create(&ssdTrd, NULL, logDaemonTrd, NULL); //end
最后再在需要的地方加上log,如 execute_one_command和 service_start函数.
打印log如下:
<4>[ 55.130331] (2)[81:init]======================logyfish start========================= <4>[ 55.130444] (2)[81:init]logyfish>|head <4>[ 55.130450] (2)[81:init]processing action 0xa43ba8 (early-init) <4>[ 55.130457] (2)[81:init]command r=0 ' write /proc/1/oom_adj -16' <4>[ 55.130464] (2)[81:init]command r=0 ' setcon u:r:init:s0' <4>[ 55.130470] (2)[81:init]starting 'ueventd' <4>[ 55.130475] (2)[81:init]==>ueventd ruunning <4>[ 55.130481] (2)[81:init]command r=0 ' start ueventd' <4>[ 55.130487] (2)[81:init]command r=0 ' mkdir /mnt 0775 root system' <4>[ 55.130494] (2)[81:init]processing action 0xa59430 (early-init) <4>[ 55.130500] (2)[81:init]processing action 0xa5a380 (e <4>[ 55.130600] (2)[81:init]logyfish>|arly-init) <4>[ 55.130606] (2)[81:init]command r=0 ' mkdir /protect_f 0771 system system' <4>[ 55.130613] (2)[81:init]command r=0 ' mkdir /protect_s 0771 system system' <4>[ 55.130621] (2)[81:init]processing action 0xa5bed0 (wait_for_coldboot_done) <4>[ 55.130628] (2)[81:init]command r=0 '' <4>[ 55.130633] (2)[81:init]processing action 0xa5bf18 (keychord_init) <4>[ 55.130640] (2)[81:init]command r=0 '' <4>[ 55.130645] (2)[81:init]processing action 0xa5bf60 (console_init) <4>[ 55.130652] (2)[81:init]command r=0 '' <4>[ 55.130657] (2)[81:init]proce <4>[ 55.130751] (2)[81:init]logyfish>|ssing action 0xa372d0 (init) <4>[ 55.130758] (2)[81:init]command r=0 ' write /proc/self/coredump_filter 39' <4>[ 55.130765] (2)[81:init]processing action 0xa43e48 (init) <4>[ 55.130772] (2)[81:init]cannot find '/system/bin/my_daemon', disabling 'my_daemon' <4>[ 55.130780] (2)[81:init]command r=0 ' start my_daemon' <4>[ 55.130786] (2)[81:init]command r=0 ' sysclktz 0' <4>[ 55.130792] (2)[81:init]command r=0 ' loglevel 6' ... <4>[ 55.132748] (2)[81:init]processing action 0xa43708 (fs_property:ro.mount.fs=EXT4) <4>[ 55.132755] (2)[81:init]cannot find '/system/bin/my_daemon', disabling 'my_daemon' <4>[ 55.132763] (2)[81:init]command r=0 ' start my_daemon' <4>[ 55.132770] (2)[81:init]processing action 0xa44c38 (fs_property:ro.mount.fs=EXT4) ...
cannot find '/system/bin/my_daemon', disabling 'my_daemon' ==>可知是此时/system分区还未就绪导致启动失败,同时这种情况下系统还会自动给 service加入 DISABLED属性:
if (stat(svc->args[0], &s) != 0) { logToBuffer("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name); svc->flags |= SVC_DISABLED; return; }
所以现在知道解决方案了,就是要确保在对应可执行文件所在文件系统就绪后再启动 service:
on post-fs-data start my_daemon
问题顺势而解!