linux 关机流程 init exit,Linux上层关机和reboot流程

从reboot命令开始

void reboot_main(void)

{

int types[] = {RB_AUTOBOOT, RB_HALT_SYSTEM, RB_POWER_OFF},

sigs[] = {SIGTERM, SIGUSR1, SIGUSR2}, idx;

if (!(toys.optflags & FLAG_n)) sync();

idx = stridx("hp", *toys.which->name)+1;

if (toys.optflags & FLAG_f)

toys.exitval = reboot(types[idx]);

else

toys.exitval = kill(1, sigs[idx]);

}

通过查看toybox中reboot命令的实现,如果存在-f选项,那么会不发送信号到init,而是直接reboot,如果不存在-f选项,那么会发送信号给init,后续关机流程由init接管。之所以要交给init处理,是为了让init对上层app进行通知处理,从而在关机前能够保存用户数据。

toys.exitval = kill(1, sigs[idx]);

这一条指令就是发送signal到进程号为1的进程,也就是我们常说的init进程。可以看到不同的reboot type,对应着不同的signale type:

RB_AUTOBOOT --- SIGTERM

RB_HALT_SYSTEM --- SIGUSR1

RB_POWER_OFF --- SIGUSR2

我们先跟一下reboot这一条线:

#include #include extern "C" int __reboot(int, int, int, void*);

int reboot(int mode) {

return __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, mode, NULL);

}

对于arm64平台它的进一步底层实现为一个系统调用bionic/libc/arch-arm64/syscalls/__reboot.S:

#include ENTRY(__reboot)

mov x8, __NR_reboot

svc #0

cmn x0, #(MAX_ERRNO + 1)

cneg x0, x0, hi

b.hi __set_errno_internal

ret

END(__reboot)

.hidden __reboot

svc会触发系统调用进入内核执行对应的系统调用。对应于magic值的定义都是统一的:

#define LINUX_REBOOT_MAGIC1 0xfee1dead

#define LINUX_REBOOT_MAGIC2 672274793

对于另外一条线,发送信号给init进程,那么后续的动作全部都会交由init进程去处理了,init进程处理和上面的方式不同的地方就是会进行一些关机前的操作,并且最终同样使用reboot系统调用触发重启或者关机。

static void set_default(void)

{

sigset_t signal_set_c;

sigatexit(SIG_DFL);

sigfillset(&signal_set_c);

sigprocmask(SIG_UNBLOCK,&signal_set_c, NULL);

run_action_from_list(SHUTDOWN);

error_msg("The system is going down NOW!");

kill(-1, SIGTERM);

error_msg("Sent SIGTERM to all processes");

sync();

sleep(1);

kill(-1,SIGKILL);

sync();

}

static void halt_poweroff_reboot_handler(int sig_no)

{

unsigned int reboot_magic_no = 0;

pid_t pid;

set_default();

switch (sig_no) {

case SIGUSR1:

error_msg("Requesting system halt");

reboot_magic_no=RB_HALT_SYSTEM;

break;

case SIGUSR2:

error_msg("Requesting system poweroff");

reboot_magic_no=RB_POWER_OFF;

break;

case SIGTERM:

error_msg("Requesting system reboot");

reboot_magic_no=RB_AUTOBOOT;

break;

default:

break;

}

sleep(1);

pid = vfork();

if (pid == 0) {

reboot(reboot_magic_no);

_exit(EXIT_SUCCESS);

}

while(1) sleep(1);

}

init进程处理关机的流程是:

先运行shutdown action list注销系统服务

运行kill(-1, SIGTERM);发送SIGTERM给系统中除了init外的所有进程

运行kill(-1,SIGKILL);发送SIGKILL给系统中除了init外的所有进程

Android平台的实现

做过高通项目的同学会发现高通自己实现了reboot的命令程序,而没有使用toybox。

#define ANDROID_RB_PROPERTY "sys.powerctl"

ret = property_set(ANDROID_RB_PROPERTY, property_val);

if (ret < 0) {

perror(cmd);

exit(EXIT_FAILURE);

}

reboot命令最终是通过设置一个android property来做此操作的,该property是sys.powerctl。那么设置此property之后系统会执行些什么呢?实际上在init进程中会监控此property并触发对应的操作。它的函数调用栈为:

property_changed -> on property sys.powerctl -> HandlePowerctlMessage ${sys.powerctl}

其init实现的内容和上面介绍的Linux系统的实现也大同小异,这里就不做赘述了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值