|
unsigned long min_coredump; /* minimal dump size */ }; 每一種可執(zhí)行文件類型被添加進(jìn)內(nèi)核時(shí),都通過(guò)函數(shù)register_binfmt將該類可執(zhí)行文對(duì)應(yīng)的linux_binfmt結(jié)構(gòu)件注冊(cè)到內(nèi)核。 static inline void register_binfmt(struct linux_binfmt *fmt) { __register_binfmt(fmt, 0); } 函數(shù)register_binfmt只是__register_binfmt的一個(gè)前端,真正完成注冊(cè)操作的函數(shù)是__register_binfmt??蓤?zhí)行文件的注冊(cè)就是將其對(duì)應(yīng)的linux_binfmt結(jié)構(gòu)鏈接到全局鏈表formats中。 void __register_binfmt(struct linux_binfmt * fmt, int insert) { BUG_ON(!fmt); write_lock(&binfmt_lock); insert ? list_add(&fmt->lh, &formats) : list_add_tail(&fmt->lh, &formats); write_unlock(&binfmt_lock); } 2 程序的運(yùn)行函數(shù) sys_execve是linux處理程序執(zhí)行的系統(tǒng)調(diào)用,函數(shù)接收的參數(shù)含義: filenamei:可執(zhí)行文件在用戶空間路徑名的地址; argv:以空字符結(jié)束的指針數(shù)組,每個(gè)指針指向一個(gè)命令行參數(shù); envp:以空字符結(jié)束的指針數(shù)組,每個(gè)字符串表示一個(gè)環(huán)境變量; regs:指向通用寄存器組的指針。 asmlinkage int sys_execve(const char __user *filenamei,const char __user *const __user *argv,const char __user *const __user *envp, struct pt_regs *regs) { int error; char * filename; 將可執(zhí)行文件路徑名從用戶空間拷到內(nèi)核空間 filename = getname(filenamei); error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; error = do_execve(filename, argv, envp, regs); putname(filename); out: return error; } 【sys_execve--->do_execve--->do_execve_common】 static int do_execve_common(const char *filename, struct user_arg_ptr argv, struct user_arg_ptr envp,struct pt_regs *regs) { struct linux_binprm *bprm; struct file *file; struct files_struct *displaced; bool clear_in_exec; int retval; const struct cred *cred = current_cred(); ...... current->flags &= ~PF_NPROC_EXCEEDED; 當(dāng)進(jìn)程剛創(chuàng)建還沒(méi)用exec運(yùn)行新程序時(shí),子進(jìn)程和父進(jìn)程共享地址空間,函數(shù)unshare_files為子進(jìn)程創(chuàng)建一個(gè)新的文件管理結(jié)構(gòu) retval = unshare_files(&displaced); if (retval) goto out_ret; 上面講述的linux_binfmt結(jié)構(gòu)描述了一種可執(zhí)行文件格式,結(jié)構(gòu)體linux_binprm描述了一個(gè)運(yùn)行的可執(zhí)行文件。動(dòng)態(tài)分配一個(gè)linux_binprm結(jié)構(gòu),將用新的可執(zhí)行文件填充該結(jié)構(gòu)。 bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); if (!bprm) goto out_files; 結(jié)構(gòu)struct cred描述用戶id、組id等于安全和權(quán)能相關(guān)的結(jié)構(gòu),函數(shù)prepare_bprm_creds將為新進(jìn)程創(chuàng)建一個(gè)新的struct cred,以脫離與父進(jìn)程的共享 retval = prepare_bprm_creds(bprm); if (retval) goto out_free; 檢測(cè)是否是一個(gè)安全的可執(zhí)行文件 retval = check_unsafe_exec(bprm); if (retval < 0) goto out_free; clear_in_exec = retval; current->in_execve = 1; 打開(kāi)可執(zhí)行文件并返回一個(gè)文件描述結(jié)構(gòu)指針 file = open_exec(filename); retval = PTR_ERR(file); if (IS_ERR(file)) goto out_unmark; 在用exec系統(tǒng)調(diào)用啟動(dòng)一個(gè)新進(jìn)程時(shí),是調(diào)度器跨越CPU移動(dòng)該進(jìn)程的一個(gè)很好的時(shí)機(jī)。這時(shí)候,該進(jìn)程尚未執(zhí)行,因此將其移動(dòng)到另一個(gè)CPU不會(huì)帶來(lái)對(duì)CPU高速緩存的負(fù)面效應(yīng)。exec系統(tǒng)調(diào)用會(huì)調(diào)用函數(shù)sched_exec挑選當(dāng)前負(fù)荷最少的CPU(而且進(jìn)程得允許在該CPU上運(yùn)行)。如果不是當(dāng)前CPU,那么會(huì)使用migration_cpu_stop,向遷移線程發(fā)送一個(gè)遷移請(qǐng)求。 sched_exec(); bprm->file = file; bprm->filename = filename; bprm->interp = filename; 為新進(jìn)程初始化一些內(nèi)存管理信息 retval = bprm_mm_init(bprm); if (retval) goto out_file; 計(jì)算命令行參數(shù)個(gè)數(shù) bprm->argc = count(argv, MAX_ARG_STRINGS); if ((retval = bprm->argc) < 0) goto out; 計(jì)算環(huán)境變量個(gè)數(shù) bprm->envc = count(envp, MAX_ARG_STRINGS); if ((retval = bprm->envc) < 0) goto out; 初始化linux_binprm結(jié)構(gòu)的euid和egid字段。用可執(zhí)行文件的前128字節(jié)填充linux_binprm的buf字段,這些字節(jié)包含用于識(shí)別可執(zhí)行文件格式的一個(gè)魔數(shù)和其他信息。 retval = prepare_binprm(bprm); if (retval < 0) goto out; 將文件路徑名拷到新進(jìn)程棧中 retval = copy_strings_kernel(1, &bprm->filename, bprm); if (retval < 0) goto out; bprm->exec = bprm->p; 將環(huán)境變量拷到進(jìn)程棧中 retval = copy_strings(bprm->envc, envp, bprm); if (retval < 0) goto out; 將命令行參數(shù)拷到棧中 retval = copy_strings(bprm->argc, argv, bprm); if (retval < 0) goto out; 函數(shù)search_binary_handler對(duì)可執(zhí)行文件格式種類鏈表formats進(jìn)行掃描,并調(diào)用每種可執(zhí)行文件結(jié)構(gòu)的load_binary方法對(duì)可執(zhí)行文件進(jìn)行操作,如果成功就停止掃描,表示找到了對(duì)應(yīng)的可執(zhí)行文件格式。 retval = search_binary_handler(bprm,regs); if (retval < 0) goto out; ...... |
|
|