kernel power off流程分析

2021-06-20 02:06:41 字數 3379 閱讀 3420

凡是

linux

核心上層關機時,底層均會調到

kernel_power_off(),

電腦可以使用按鍵

ctr+alt+del

鍵進入關機,下面我們看看**流程:

syscall_define4() -> kernel_power_off

()-> pm_power_off_prepare() -> machine_power_off()->    pm_power_off()

在這裡我想說的是pm_power_off_prepare()

和pm_power_off()

都是與平台相關,有些平台只有填充

pm_power_off

而pm_power_off_prepare

並沒有填充。而在

pm_power_off

()函式中一般函式不能被呼叫因為整個

syscore

已經關閉,系統不能呼叫

idle thread

。所以關機前我們通常在

pm_power_off_prepare

()函式來實現,關機前通常很有可能需要完成的其他事,我們在這裡就可以填充。

* function pointers to optional machine specific functions

void (*pm_power_off)(void);

export_symbol(pm_power_off);

* if set, this is used for preparing the system to power off.

void (*pm_power_off_prepare)(void);

例如我們在高通平台所加的:

在arch/arm/mach-msm/restart.c

static int __init msm_restart_init(void)

pm_power_off = msm_power_off;

pm_power_off_prepare = msm_power_off_prepare;

源**:

kernel/sys.c

syscall_define4(reboot, int, magic1, int, magic2, unsigned int, cmd,

void __user *, arg)

char buffer[256];

int ret = 0;

/* we only trust the superuser with rebooting the system. */

if (!capable(cap_sys_boot))

return -eperm;

/* for safety, we require "magic" arguments. */

if (magic1 != linux_reboot_magic1 ||

(magic2 != linux_reboot_magic2 &&

magic2 != linux_reboot_magic2a &&

magic2 != linux_reboot_magic2b &&

magic2 != linux_reboot_magic2c))

return -einval;

/* instead of trying to make the power_off code look like

* halt when pm_power_off is not set do it the easy way.

if ((cmd == linux_reboot_cmd_power_off) && !pm_power_off)

cmd = linux_reboot_cmd_halt;

mutex_lock(&reboot_mutex);

switch (cmd) {

case linux_reboot_cmd_restart:

kernel_restart(null);

break;

case linux_reboot_cmd_cad_on:

c_a_d = 1;

break;

case linux_reboot_cmd_cad_off:

c_a_d = 0;

break;

case linux_reboot_cmd_halt:

kernel_halt();

do_exit(0);

panic("cannot halt");

case linux_reboot_cmd_power_off:

kernel_power_off();

do_exit(0);

break;

case linux_reboot_cmd_restart2:

if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) {

ret = -efault;

break;

buffer[sizeof(buffer) - 1] = '\0';

kernel_restart(buffer);

break;

#ifdef config_kexec

case linux_reboot_cmd_kexec:

ret = kernel_kexec();

break;

#endif

#ifdef config_hibernation

case linux_reboot_cmd_sw_suspend:

ret = hibernate();

break;

#endif

default:

ret = -einval;

break;

mutex_unlock(&reboot_mutex);

return ret;

void kernel_power_off(void)

kernel_shutdown_prepare(system_power_off);

if (pm_power_off_prepare)

pm_power_off_prepare();

disable_nonboot_cpus();

syscore_shutdown();

printk(kern_emerg "power down.\n");

kmsg_dump(kmsg_dump_poweroff);

machine_power_off();

void machine_power_off(void)

machine_shutdown();

if (pm_power_off)

pm_power_off();

網路流 費用流

這個好像不考 沒事可以騙分 費用流,顧名思義,就是有費用的流,也就是說,給乙個網路流圖中的每條弧增加乙個單位流量費用。一般來說求解的費用流都是最大流最小費用。好像沒什麼好bb的 這裡推薦使用zkw演算法求解最小費用流,看著 理解就行,應該還是很好理解的。zkw演算法在稠密圖上跑得飛快,在稀疏圖上還不...

IO流 記憶體流

記憶體流 bytearrayinputstream bytearrayoutputstream chararrayinputstream charoutputstream stringreader stringwriter 目的 將資料臨時存放在陣列中 相當於記憶體中 tips 上面的writer ...

網路流 費用流

網路流有很多種類 其中最大流 有增廣路演算法和預流推進演算法。增廣路演算法就是不斷的新增增廣路。其中的dinic演算法。會稍微提到isap演算法 poj1273 首先想到dfs一直往後延伸,然後從源點到匯點計算每條路,但是這樣只是單條路的最值,有時可能因為走一條路而間接的認定了除這條路以外的某個路通...