进程退出的exitcode
错误信息
内核打印
1 | Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b |
分析
出错位置
1 | panic("Attempted to kill init! exitcode=0x%08x\n", |
kernel/exit.c
exit_cede赋值
1 | void do_exit(long code) |
函数调用关系:
1 | exit_notify |
错误来源
在Android系统中,linux内核启动过程中,进入用户空间
后,init进程执行过程中出现该错误
由于在用户空间引起的内核错误,因此只能通过系统调用产生
1 | SYSCALL_DEFINE1(exit, int, error_code) |
在进入内核是do_exit取了用户空间传入的错误码的低8位
进程退出的错误码
在系统中的进程在正常和非正常退出时,都有一个表示当前进程退出状态的标识,即退出码
查看进程退出码
退出码代表的是一个进程退出的状态码, 可以使用wait函数进行查看。
1 | void _exit(int status), |
status表明了进程终止时的状态。当子进程使用_exit()后,父进程如果在用wait()等待子进程,那么wait()将会返回status状态,注意只有status的低8位(0~255)会返回给父进程
1 |
|
正常退出结果:
1 | =====>$./a.out |
在子进程sleep时将其kill掉的结果:
1 | =====>$./a.out & |
在进程正常退出时,子进程的状态码是0
,而kill掉后变为了15
.
注:此时如果在linux终端下使用
echo $?
,获取的仅仅该进程的main函数的返回值。
退出码的含义
根据前面分析,在进程调用_exit退出时,是通过exit系统调用实现的,而这里的0
和15
,就是系统调用exit的参数error_code
进程的退出状态不等于退出码,程退出时候的状态码是8位,高4位存储退出码,低4位存储导致进程退出的信号标志位
网上有人说16位,分别是高八位和低八位,还需确认
根据这段话的描述,之前测试中子进程的退出状态0
和15
中,退出码均为0
,而退出时的singal不同,正常退出时为0,kill掉后变为15
制造段错误
在测试case中的子进程中,制造一个段错误,根据此时的分析子进程退出的状态码中的signal应该代表段错误
子进程中添加:
1 | int *a; |
测试结果:
1 | =====>$./a.out |
此时子进程的退出码=8
,而signal=b
信号
linux内核中x86的信号列表:
1 |
arch/x86/include/uapi/asm/signal.h
信号 | 行为 | 产生原因 |
---|---|---|
SIGTERM | 请求中断 | kill() 可以发 SIGTERM 过去;kill 命令默认也使用 SIGTERM 信号 |
SIGSEGV | 无效内存引用 | 段错误 |
总结
进程在退出时都会将自己当前的状态告诉内核,而此时的状态码
包含两种含义:
- 高4位代表当前进程的退出码
- 低4位代表使当前进程退出所使用的信号
在本文最开始提到的错误也是由于SIGSEGV
无效内存引用引起的。
mips架构下的信号列表:
1 |
arch/mips/include/uapi/asm/signal.h
参考:
- linux子进程退出状态值解析:waitpid() status意义解析