8.html
来自「linux 0.11中文版 有注释」· HTML 代码 · 共 573 行 · 第 1/4 页
HTML
573 行
<a name='L268'> <b>__asm__</b> ("pushl $0x17\n\tpop %%fs"::);
<a name='L269'><i><font color='green'>// 将参数和环境空间已存放数据的页面(共可有MAX_ARG_PAGES 页,128kB)放到数据段线性地址的</font></i>
<a name='L270'><i><font color='green'>// 末端。是调用函数put_page()进行操作的(mm/memory.c, 197)。</font></i>
<a name='L271'> data_base += data_limit;
<a name='L272'> <b>for</b> (<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> = <a href='../S/8.html#L55' title='Defined at 55 in fs/exec.c.'>MAX_ARG_PAGES</a> - 1; <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> >= 0; <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>--)
<a name='L273'> <font color='red'>{</font>
<a name='L274'> data_base -= <a href='../D/324.html' title='Multiple defined in 4 places.'>PAGE_SIZE</a>;
<a name='L275'> <b>if</b> (page[<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>]) <i><font color='green'>// 如果该页面存在,</font></i>
<a name='L276'> <a href='../S/94.html#L306' title='Defined at 306 in mm/memory.c.'>put_page</a> (page[<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>], data_base); <i><font color='green'>// 就放置该页面。</font></i>
<a name='L277'> <font color='red'>}</font>
<a name='L278'> <b>return</b> data_limit; <i><font color='green'>// 最后返回数据段限长(64MB)。</font></i>
<a name='L279'><font color='red'>}</font>
<a name='L280'>
<a name='L281'><i><font color='green'>/*</font></i>
<a name='L282'><i><font color='green'>* 'do_execve()' executes a new program.</font></i>
<a name='L283'><i><font color='green'>*/</font></i>
<a name='L284'><i><font color='green'>/*</font></i>
<a name='L285'><i><font color='green'>* 'do_execve()'函数执行一个新程序。</font></i>
<a name='L286'><i><font color='green'>*/</font></i>
<a name='L287'><i><font color='green'>//// execve()系统中断调用函数。加载并执行子进程(其它程序)。</font></i>
<a name='L288'><i><font color='green'>// 该函数系统中断调用(int 0x80)功能号__NR_execve 调用的函数。</font></i>
<a name='L289'><i><font color='green'>// 参数:eip - 指向堆栈中调用系统中断的程序代码指针eip 处,参见kernel/system_call.s 程序</font></i>
<a name='L290'><i><font color='green'>// 开始部分的说明;tmp - 系统中断调用本函数时的返回地址,无用;</font></i>
<a name='L291'><i><font color='green'>// filename - 被执行程序文件名;argv - 命令行参数指针数组;envp - 环境变量指针数组。</font></i>
<a name='L292'><i><font color='green'>// 返回:如果调用成功,则不返回;否则设置出错号,并返回-1。</font></i>
<a name='L293'><b>int</b>
<a name='L294'><a href='../S/77.html#L262' title='Refered from 262 in kernel/system_call.s.'>do_execve</a> (<b>unsigned</b> <b>long</b> *eip, <b>long</b> tmp, <b>char</b> *filename,
<a name='L295'> <b>char</b> **argv, <b>char</b> **envp)
<a name='L296'><font color='red'>{</font>
<a name='L297'> <b>struct</b> m_inode *inode; <i><font color='green'>// 内存中I 节点指针结构变量。</font></i>
<a name='L298'> <b>struct</b> buffer_head *bh; <i><font color='green'>// 高速缓存块头指针。</font></i>
<a name='L299'> <b>struct</b> exec ex; <i><font color='green'>// 执行文件头部数据结构变量。</font></i>
<a name='L300'> <b>unsigned</b> <b>long</b> page[<a href='../S/8.html#L55' title='Defined at 55 in fs/exec.c.'>MAX_ARG_PAGES</a>]; <i><font color='green'>// 参数和环境字符串空间的页面指针数组。</font></i>
<a name='L301'> <b>int</b> <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>, argc, envc;
<a name='L302'> <b>int</b> e_uid, e_gid; <i><font color='green'>// 有效用户id 和有效组id。</font></i>
<a name='L303'> <b>int</b> retval; <i><font color='green'>// 返回值。</font></i>
<a name='L304'> <b>int</b> sh_bang = 0; <i><font color='green'>// 控制是否需要执行脚本处理代码。</font></i>
<a name='L305'><i><font color='green'>// 参数和环境字符串空间中的偏移指针,初始化为指向该空间的最后一个长字处。</font></i>
<a name='L306'> <b>unsigned</b> <b>long</b> p = <a href='../D/324.html' title='Multiple defined in 4 places.'>PAGE_SIZE</a> * <a href='../S/8.html#L55' title='Defined at 55 in fs/exec.c.'>MAX_ARG_PAGES</a> - 4;
<a name='L307'>
<a name='L308'><i><font color='green'>// eip[1]中是原代码段寄存器cs,其中的选择符不可以是内核段选择符,也即内核不能调用本函数。</font></i>
<a name='L309'> <b>if</b> ((0xffff & eip[1]) != 0x000f)
<a name='L310'> <a href='../S/72.html#L24' title='Defined at 24 in kernel/panic.c.'>panic</a> ("execve called from supervisor mode");
<a name='L311'><i><font color='green'>// 初始化参数和环境串空间的页面指针数组(表)。</font></i>
<a name='L312'> <b>for</b> (<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> = 0; <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> < <a href='../S/8.html#L55' title='Defined at 55 in fs/exec.c.'>MAX_ARG_PAGES</a>; <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>++) <i><font color='green'>/* clear page-table */</font></i>
<a name='L313'> page[<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>] = 0;
<a name='L314'><i><font color='green'>// 取可执行文件的对应i 节点号。</font></i>
<a name='L315'> <b>if</b> (!(inode = <a href='../S/14.html#L470' title='Defined at 470 in fs/namei.c.'>namei</a> (filename))) <i><font color='green'>/* get executables inode */</font></i>
<a name='L316'> <b>return</b> -<a href='../S/28.html#L31' title='Defined at 31 in include/errno.h.'>ENOENT</a>;
<a name='L317'><i><font color='green'>// 计算参数个数和环境变量个数。</font></i>
<a name='L318'> argc = <a href='../D/738.html' title='Multiple defined in 17 places.'>count</a> (argv);
<a name='L319'> envc = <a href='../D/738.html' title='Multiple defined in 17 places.'>count</a> (envp);
<a name='L320'>
<a name='L321'><i><font color='green'>// 执行文件必须是常规文件。若不是常规文件则置出错返回码,跳转到exec_error2(第347 行)。</font></i>
<a name='L322'>restart_interp:
<a name='L323'> <b>if</b> (!<a href='../S/43.html#L34' title='Defined at 34 in include/sys/stat.h.'>S_ISREG</a> (inode->i_mode))
<a name='L324'> <font color='red'>{</font> <i><font color='green'>/* must be regular file */</font></i>
<a name='L325'> retval = -<a href='../S/28.html#L42' title='Defined at 42 in include/errno.h.'>EACCES</a>;
<a name='L326'> <b>goto</b> exec_error2;
<a name='L327'> <font color='red'>}</font>
<a name='L328'><i><font color='green'>// 检查被执行文件的执行权限。根据其属性(对应i 节点的uid 和gid),看本进程是否有权执行它。</font></i>
<a name='L329'> <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> = inode->i_mode;
<a name='L330'> e_uid = (<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> & <a href='../S/43.html#L30' title='Defined at 30 in include/sys/stat.h.'>S_ISUID</a>) ? inode->i_uid : current->euid;
<a name='L331'> e_gid = (<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> & <a href='../S/43.html#L31' title='Defined at 31 in include/sys/stat.h.'>S_ISGID</a>) ? inode->i_gid : current->egid;
<a name='L332'> <b>if</b> (current->euid == inode->i_uid)
<a name='L333'> <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> >>= 6;
<a name='L334'> <b>else</b> <b>if</b> (current->egid == inode->i_gid)
<a name='L335'> <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> >>= 3;
<a name='L336'> <b>if</b> (!(<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> & 1) && !((inode->i_mode & 0111) && <a href='../S/34.html#L37' title='Defined at 37 in include/linux/kernel.h.'>suser</a> ()))
<a name='L337'> <font color='red'>{</font>
<a name='L338'> retval = -<a href='../S/28.html#L37' title='Defined at 37 in include/errno.h.'>ENOEXEC</a>;
<a name='L339'> <b>goto</b> exec_error2;
<a name='L340'> <font color='red'>}</font>
<a name='L341'><i><font color='green'>// 读取执行文件的第一块数据到高速缓冲区,若出错则置出错码,跳转到exec_error2 处去处理。</font></i>
<a name='L342'> <b>if</b> (!(bh = <a href='../S/6.html#L397' title='Defined at 397 in fs/buffer.c.'>bread</a> (inode->i_dev, inode->i_zone[0])))
<a name='L343'> <font color='red'>{</font>
<a name='L344'> retval = -<a href='../S/28.html#L42' title='Defined at 42 in include/errno.h.'>EACCES</a>;
<a name='L345'> <b>goto</b> exec_error2;
<a name='L346'> <font color='red'>}</font>
<a name='L347'><i><font color='green'>// 下面对执行文件的头结构数据进行处理,首先让ex 指向执行头部分的数据结构。</font></i>
<a name='L348'> ex = *((<b>struct</b> exec *) bh->b_data); <i><font color='green'>/* read exec-header */</font></i><i><font color='green'>/* 读取执行头部分 */</font></i>
<a name='L349'><i><font color='green'>// 如果执行文件开始的两个字节为'#!',并且sh_bang 标志没有置位,则处理脚本文件的执行。</font></i>
<a name='L350'> <b>if</b> ((bh->b_data[0] == '#') && (bh->b_data[1] == '!') && (!sh_bang))
<a name='L351'> <font color='red'>{</font>
<a name='L352'><i><font color='green'>/*</font></i>
<a name='L353'><i><font color='green'>* This section does the #! interpretation.</font></i>
<a name='L354'><i><font color='green'>* Sorta complicated, but hopefully it will work. -TYT</font></i>
<a name='L355'><i><font color='green'>*/</font></i>
<a name='L356'><i><font color='green'>/*</font></i>
<a name='L357'><i><font color='green'>* 这部分处理对'#!'的解释,有些复杂,但希望能工作。-TYT</font></i>
<a name='L358'><i><font color='green'>*/</font></i>
<a name='L359'>
<a name='L360'> <b>char</b> <a href='../D/716.html' title='Multiple defined in 16 places.'>buf</a>[1023], *cp, *interp, *i_name, *i_arg;
<a name='L361'> <b>unsigned</b> <b>long</b> old_fs;
<a name='L362'>
<a name='L363'><i><font color='green'>// 复制执行程序头一行字符'#!'后面的字符串到buf 中,其中含有脚本处理程序名。</font></i>
<a name='L364'> <a href='../S/42.html#L56' title='Defined at 56 in include/string.h.'>strncpy</a> (<a href='../D/716.html' title='Multiple defined in 16 places.'>buf</a>, bh->b_data + 2, 1022);
<a name='L365'><i><font color='green'>// 释放高速缓冲块和该执行文件i 节点。</font></i>
<a name='L366'> <a href='../S/6.html#L377' title='Defined at 377 in fs/buffer.c.'>brelse</a> (bh);
<a name='L367'> <a href='../S/12.html#L221' title='Defined at 221 in fs/inode.c.'>iput</a> (inode);
<a name='L368'><i><font color='green'>// 取第一行内容,并删除开始的空格、制表符。</font></i>
<a name='L369'> <a href='../D/716.html' title='Multiple defined in 16 places.'>buf</a>[1022] = '\0';
<a name='L370'> <b>if</b> (cp = <a href='../S/42.html#L168' title='Defined at 168 in include/string.h.'>strchr</a> (<a href='../D/716.html' title='Multiple defined in 16 places.'>buf</a>, '\n'))
<a name='L371'> <font color='red'>{</font>
<a name='L372'> *cp = '\0';
<a name='L373'> <b>for</b> (cp = <a href='../D/716.html' title='Multiple defined in 16 places.'>buf</a>; (*cp == ' ') || (*cp == '\t'); cp++);
<a name='L374'> <font color='red'>}</font>
<a name='L375'><i><font color='green'>// 若该行没有其它内容,则出错。置出错码,跳转到exec_error1 处。</font></i>
<a name='L376'> <b>if</b> (!cp || *cp == '\0')
<a name='L377'> <font color='red'>{</font>
<a name='L378'> retval = -<a href='../S/28.html#L37' title='Defined at 37 in include/errno.h.'>ENOEXEC</a>; <i><font color='green'>/* No interpreter name found */</font></i>
<a name='L379'> <b>goto</b> exec_error1;
<a name='L380'> <font color='red'>}</font>
<a name='L381'><i><font color='green'>// 否则就得到了开头是脚本解释执行程序名称的一行内容。</font></i>
<a name='L382'> interp = i_name = cp;
<a name='L383'><i><font color='green'>// 下面分析该行。首先取第一个字符串,其应该是脚本解释程序名,iname 指向该名称。</font></i>
<a name='L384'> i_arg = 0;
<a name='L385'> <b>for</b> (; *cp && (*cp != ' ') && (*cp != '\t'); cp++)
<a name='L386'> <font color='red'>{</font>
<a name='L387'> <b>if</b> (*cp == '/')
<a name='L388'> i_name = cp + 1;
<a name='L389'> <font color='red'>}</font>
<a name='L390'><i><font color='green'>// 若文件名后还有字符,则应该是参数串,令i_arg 指向该串。</font></i>
<a name='L391'> <b>if</b> (*cp)
<a name='L392'> <font color='red'>{</font>
<a name='L393'> *cp++ = '\0';
<a name='L394'> i_arg = cp;
<a name='L395'> <font color='red'>}</font>
<a name='L396'><i><font color='green'>/*</font></i>
<a name='L397'><i><font color='green'>* OK, we've parsed out the interpreter name and</font></i>
<a name='L398'><i><font color='green'>* (optional) argument.</font></i>
<a name='L399'><i><font color='green'>*/</font></i>
<a name='L400'><i><font color='green'>/*</font></i>
<a name='L401'><i><font color='green'>* OK,我们已经解析出解释程序的文件名以及(可选的)参数。</font></i>
<a name='L402'><i><font color='green'>*/</font></i>
<a name='L403'><i><font color='green'>// 若sh_bang 标志没有设置,则设置它,并复制指定个数的环境变量串和参数串到参数和环境空间中。</font></i>
<a name='L404'> <b>if</b> (sh_bang++ == 0)
<a name='L405'> <font color='red'>{</font>
<a name='L406'> p = <a href='../S/8.html#L166' title='Defined at 166 in fs/exec.c.'>copy_strings</a> (envc, envp, page, p, 0);
<a name='L407'> p = <a href='../S/8.html#L166' title='Defined at 166 in fs/exec.c.'>copy_strings</a> (--argc, argv + 1, page, p, 0);
<a name='L408'> <font color='red'>}</font>
<a name='L409'><i><font color='green'>/*</font></i>
<a name='L410'><i><font color='green'>* Splice in (1) the interpreter's name for argv[0]</font></i>
<a name='L411'><i><font color='green'>* (2) (optional) argument to interpreter</font></i>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?