系统初始化时kernel_init在内核态创建和运行应用程序以完成系统初始化
?系統(tǒng)初始化時(shí)kernel_init在內(nèi)核態(tài)創(chuàng)建和運(yùn)行應(yīng)用程序以完成系統(tǒng)初始化.? 內(nèi)核剛剛啟動時(shí),只有內(nèi)核態(tài)的代碼,后來在init過程中,在內(nèi)核態(tài)運(yùn)行了一些初始化系統(tǒng)的程序,才產(chǎn)生了工作在用戶空間的進(jìn)程。
從內(nèi)核里發(fā)起系統(tǒng)調(diào)用,執(zhí)行用戶空間的應(yīng)用程序。這些程序自動以root權(quán)限運(yùn)行。
? ? ? ? 這里,內(nèi)核以此運(yùn)行用戶空間程序,從而產(chǎn)生了第一個(gè)以及后續(xù)的用戶空間程序。一般用戶空間的init程序,會啟動一個(gè)shell,供用戶登錄系統(tǒng)用。這樣,這里啟動的用戶空間的程序永遠(yuǎn)不會返回。也就是說,正常情況下不會到panic這一步。系統(tǒng)執(zhí)行到這里后,Linux Kernel的初始化就完成了。
此時(shí),中斷和中斷驅(qū)動的進(jìn)程調(diào)度機(jī)制,調(diào)度著各個(gè)線程在各個(gè)CPU上的運(yùn)行。中斷處理程序不時(shí)被觸發(fā)。操作系統(tǒng)上,一些內(nèi)核線程在內(nèi)核態(tài)運(yùn)行,它們永遠(yuǎn)不會進(jìn)入用戶態(tài)。它們也根本沒有用戶態(tài)的內(nèi)存空間。它的線性地址空間就是共享內(nèi)核的線性地址空間。一些用戶進(jìn)程通常在用戶態(tài)運(yùn)行。有時(shí)因?yàn)橄到y(tǒng)調(diào)用而進(jìn)入內(nèi)核態(tài),調(diào)用內(nèi)核提供的系統(tǒng)調(diào)用處理函數(shù)。
? ? ? ?但有時(shí),我們的內(nèi)核模塊或者內(nèi)核線程希望能夠調(diào)用用戶空間的進(jìn)程,就像系統(tǒng)啟動之初init_post函數(shù)做的那樣。
? ? ? ?如,一個(gè)驅(qū)動從內(nèi)核得到了主從設(shè)備號,然后需要使用mknod命令創(chuàng)建相應(yīng)的設(shè)備文件,以供用戶調(diào)用該設(shè)備。
? ? ? ?如,一個(gè)內(nèi)核線程想神不知鬼不覺地偷偷運(yùn)行個(gè)有特權(quán)的后門程序。等等之類的需求。
call_usermodehelper函數(shù)
? ? ? ? ??Linux ?Kernel提供了call_usermodehelper函數(shù),讓我們能夠異常方便地在內(nèi)核中直接新建和運(yùn)行用戶空間程序,并且該程序具有root權(quán)限。
call_usermodehelper函數(shù)源碼
include/linux/kmod.h頭文件
105static inline int106call_usermodehelper(char *path, char **argv, char **envp, enum umh_wait wait)107{108 return call_usermodehelper_fns(path, argv, envp, wait,109 NULL, NULL, NULL);110}11150enum umh_wait {51 UMH_NO_WAIT = -1, /* don't wait at all */52 UMH_WAIT_EXEC = 0, /* wait for the exec, but not the process */53 UMH_WAIT_PROC = 1, /* wait for the process to complete */54};5556struct subprocess_info {57 struct work_struct work;58 struct completion *complete;59 char *path;60 char **argv;61 char **envp;62 enum umh_wait wait;63 int retval;64 int (*init)(struct subprocess_info *info);65 void (*cleanup)(struct subprocess_info *info);66 void *data;67};68 kernel/kmod.c實(shí)現(xiàn)文件 377/**378 * call_usermodehelper_exec - start a usermode application379 * @sub_info: information about the subprocessa 子進(jìn)程的信息380 * @wait: wait for the application to finish and return status.等待用戶空間子進(jìn)程的完成,并返回結(jié)果。381 * when -1 don't wait at all, but you get no useful error back when382 * the program couldn't be exec'ed. This makes it safe to call383 * from interrupt context.
-1表示根本不等待子進(jìn)程的結(jié)束。 但這樣你就無法對程序出錯(cuò)進(jìn)行處理。
如果使用中斷上下文,那么應(yīng)該使用-1。
call_usermodehelper_exec函數(shù),啟動一個(gè)用戶模式應(yīng)用程序。
如果不設(shè)置wait,那么用戶空間應(yīng)用程序會被異步啟動。 ?它在root權(quán)限下運(yùn)行。是keventd進(jìn)程的子進(jìn)程。
如果等待子進(jìn)程完成,那么執(zhí)行等待完成的 ?事件通知和喚醒。就是說當(dāng)前進(jìn)程sleep。
?
?
? ? ?call_usermodeheler函數(shù)創(chuàng)建的新程序,實(shí)際上作為keventd內(nèi)核線程的子進(jìn)程運(yùn)行,因此具有root權(quán)限。? 新程序被扔到內(nèi)核工作隊(duì)列“khelper”中進(jìn)行執(zhí)行。
? ? ? 如果使用UMH_NO_WAIT,那么因?yàn)闆]有在事件隊(duì)列上等待和喚醒的過程,因此可以在中斷上下文中使用。?它的返回值是新程序的返回值。
?
call_usermodeheler函數(shù)的參數(shù)用法和execve函數(shù)一致?
#include<unistd.h>
intexecve(const char *filename, char *const?argv[],
char*const?envp[]);
execve函數(shù)使用sys_execve系統(tǒng)調(diào)用,創(chuàng)建并運(yùn)行一個(gè)程序。
argv是字符串?dāng)?shù)組,是將被傳輸?shù)叫鲁绦虻膮?shù)。
envp是字符串?dāng)?shù)組,格式是key=value,是傳遞給新程序的環(huán)境變量。
argv和envp都必須以NULL字符串結(jié)束。以此來實(shí)現(xiàn)對字符串?dāng)?shù)組的大小統(tǒng)計(jì)。?
? ? ?這就意味著,argv的第一個(gè)參數(shù)也必須是程序名。也就是說,新程序名要在execve函數(shù)的參數(shù)中傳遞兩次。
?
? ? ?這和main函數(shù)傳入的參數(shù)格式也是一致的。
編譯上述模塊的命令:
make-C /lib/modules/`uname -r`/build M=`pwd` modules
然后使用insmod和rmmod命令加載和卸載驅(qū)動。可以看到上述命令創(chuàng)建了文件和刪除了創(chuàng)建的文件。
總結(jié)
以上是生活随笔為你收集整理的系统初始化时kernel_init在内核态创建和运行应用程序以完成系统初始化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android4.0 编译报错 Xmx2
- 下一篇: inotify 文件系统监控