linux-2.6.11-exec
来源:互联网 发布:html input value js 编辑:程序博客网 时间:2024/05/22 05:02
在unistd.h中 asmlinkage int sys_execve(struct pt_regs regs);
进入函数实现,在process.c中
asmlinkage int sys_execve(struct pt_regs regs){ int error; char * filename; filename = getname((char __user *) regs.ebx); error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; error = do_execve(filename, (char __user * __user *) regs.ecx, (char __user * __user *) regs.edx, ®s);//核心函数 if (error == 0) { task_lock(current); current->ptrace &= ~PT_DTRACE; task_unlock(current); /* Make sure we don't return using sysenter.. */ set_thread_flag(TIF_IRET); } putname(filename);out: return error;}
它调用了do_exec
do_execve(filename,(char __user * __user *) regs.ecx,(char __user * __user *) regs.edx,®s);
一共是四个参数,看一下我们调用的exec族的函数原型
int execl(const char *path, const char *arg, ...) int execv(const char *path, char *const argv[]) int execle(const char *path, const char *arg, ..., char *const envp[]) int execve(const char *path, char *const argv[], char *const envp[]) int execlp(const char *file, const char *arg, ...) int execvp(const char *file, char *const argv[])
作对比可知,第一个参数都是文件名称,其余参数都是由regs这个结构体代进去的,看一下regs结构体好了
struct pt_regs { long ebx;//存放文件名称 long ecx;//参数1 long edx;//环境变量 long esi; long edi; long ebp; long eax; int xds; int xes; long orig_eax; long eip; int xcs; long eflags; long esp; int xss;};
这个结构体里存的是寄存器,在ptrace.h中定义
看一下do_execve的函数原型
int do_execve(char * filename, char __user *__user *argv, char __user *__user *envp, struct pt_regs * regs)
在这个函数中定义了一个struct linux_binprm 类型的结构体指针*bprm,这个结构用来保存装载二进制文件时使用的参数。
struct linux_binprm{ char buf[BINPRM_BUF_SIZE]; struct page *page[MAX_ARG_PAGES]; struct mm_struct *mm;//k unsigned long p; /* current top of mem */ int sh_bang; struct file * file; int e_uid, e_gid; kernel_cap_t cap_inheritable, cap_permitted, cap_effective; void *security; int argc, envc; char * filename; /* Name of binary as seen by procps */ /* Name of the binary really executed. Most of the time same as filename, but could be different for binfmt_{misc,script} */ unsigned interp_flags; unsigned interp_data; unsigned long loader, exec;};
为它申请空间并置0
bprm = kmalloc(sizeof(*bprm), GFP_KERNEL); if (!bprm) goto out_ret; memset(bprm, 0, sizeof(*bprm));
然后调用struct file *open_exec(const char *name)函数,在此函数中调用path_lookup,dentry_open,path_release三个函数以获得与可执行文件相关的目录项对象、文件对象和索引结点对象。
struct file *open_exec(const char *name){ struct nameidata nd; int err; struct file *file; nd.intent.open.flags = FMODE_READ; /** * 调用path_lookup,dentry_open,path_release以获得与可执行文件 * 相关的目录项对象、文件对象和索引结点对象。 */ err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_OPEN, &nd); file = ERR_PTR(err); if (!err) { struct inode *inode = nd.dentry->d_inode; file = ERR_PTR(-EACCES); if (!(nd.mnt->mnt_flags & MNT_NOEXEC) && S_ISREG(inode->i_mode)) { /** * 检查执行权限 */ int err = permission(inode, MAY_EXEC, &nd); if (!err && !(inode->i_mode & 0111)) err = -EACCES; file = ERR_PTR(err); if (!err) { file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);//打开一个目录项 if (!IS_ERR(file)) { /** * deny_write_access通过检查索引结点的i_writecount字段, * 确定可执行文件没有被写入。并把-1存放在这个字段以禁止进一步的写访问 */ err = deny_write_access(file); if (err) { fput(file); file = ERR_PTR(err); } }out: return file; } } path_release(&nd); } goto out;}
出来之后经过多项检查,调用sched_exec()确定最小负载CPU以执行新程序,并把当前进程转移过去。
这步完成之后进行对部分参数进行赋值
bprm->p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); bprm->file = file; bprm->filename = filename; bprm->interp = filename; bprm->mm = mm_alloc(); retval = -ENOMEM; if (!bprm->mm) goto out_file;
注:bprm是struct linux_binprm 类型的结构体指针
/** * 把路径名,命令行参数,环境串复制到一个或者多个新分配的页框中, * 最终,它们会被分配给用户态地址空间 */ retval = copy_strings_kernel(1, &bprm->filename, bprm); if (retval < 0) goto out; bprm->exec = bprm->p; retval = copy_strings(bprm->envc, envp, bprm); if (retval < 0) goto out; retval = copy_strings(bprm->argc, argv, bprm); if (retval < 0) goto out;
下面调用了search_binary_handler(bprm,regs);
int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
在search_binary_handler中定义了一个结构体struct exec * eh,在A.out.h中定义
struct exec{ unsigned long a_info; /使用宏的N_MAGIC */ unsigned a_text; /* length of text, in bytes */ unsigned a_data; /* length of data, in bytes */ unsigned a_bss; /* 用字节表示文件的未初始化数据区域的长度*/ unsigned a_syms; /* 文件中符号表数据的长度,以字节为单位*/ unsigned a_entry; /* start address */ unsigned a_trsize; /* 文本的重新定位信息的长度,以字节为单位*/ unsigned a_drsize; /* 数据的重新定位信息的长度,以字节为单位*/};
看一下内核对cpu的操作代码
/** * 所有CPU的运行队列。 */static DEFINE_PER_CPU(struct runqueue, runqueues);#define for_each_domain(cpu, domain) \ for (domain = cpu_rq(cpu)->sd; domain; domain = domain->parent)/** * 该宏产生索引为n的CPU的运行队列的地址。 */#define cpu_rq(cpu) (&per_cpu(runqueues, (cpu)))/** * 该宏产生本地CPU的运行队列的地址。 */#define this_rq() (&__get_cpu_var(runqueues))/** * 该宏产生任务所在的运行队列的地址。 */#define task_rq(p) cpu_rq(task_cpu(p))/** * 该宏产生索引为n的CPU的运行队列的当前任务。 */#define cpu_curr(cpu) (cpu_rq(cpu)->curr)/*
阅读全文
0 0
- linux-2.6.11-exec
- linux exec
- linux-exec
- linux exec
- Linux exec
- Linux exec函数族
- Linux exec函数族
- linux find exec rm
- linux exec命令
- linux find exec rm
- Linux exec函数族
- linux exec的用法
- Linux exec函数族
- linux exec函数族
- Linux exec函数调用
- linux exec函数族
- linux exec的用法
- linux exec的用法
- 剑指offer面试题60 把二叉树打印成多行(Java实现)
- java基础的一些理解
- updateByPrimaryKey和updateByPrimaryKeySelective insert和insertSelective
- bzoj2141[排队]
- MyEclipse 配置
- linux-2.6.11-exec
- robots协议
- java登录验证码(框架版)
- 动态sql
- 挑战数据结构与算法面试题——80题全解析(三)
- 再说String
- 月份转英文
- POJ1703 Find them, Catch them (分类并查集)
- [学习笔记]关于在MVC上实现Devexpress组件