unsigned long min_coredump; /* minimal dump size */
};
每一種可執(zhí)行文件類(lèi)型被添加進(jìn)內(nèi)核時(shí),都通過(guò)函數(shù)register_binfmt將該類(lèi)可執(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í)行文件在用戶(hù)空間路徑名的地址;
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í)行文件路徑名從用戶(hù)空間拷到內(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描述用戶(hù)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í)行文件格式種類(lèi)鏈表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;
......
聯(lián)系客服