8.html
来自「linux 0.11中文版 有注释」· HTML 代码 · 共 573 行 · 第 1/4 页
HTML
573 行
<a name='L124'> <b>return</b> <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>;
<a name='L125'><font color='red'>}</font>
<a name='L126'>
<a name='L127'><i><font color='green'>/*</font></i>
<a name='L128'><i><font color='green'>* 'copy_string()' copies argument/envelope strings from user</font></i>
<a name='L129'><i><font color='green'>* memory to free pages in kernel mem. These are in a format ready</font></i>
<a name='L130'><i><font color='green'>* to be put directly into the top of new user memory.</font></i>
<a name='L131'><i><font color='green'>*</font></i>
<a name='L132'><i><font color='green'>* Modified by TYT, 11/24/91 to add the from_kmem argument, which specifies</font></i>
<a name='L133'><i><font color='green'>* whether the string and the string array are from user or kernel segments:</font></i>
<a name='L134'><i><font color='green'>*</font></i>
<a name='L135'><i><font color='green'>* from_kmem argv * argv **</font></i>
<a name='L136'><i><font color='green'>* 0 user space user space</font></i>
<a name='L137'><i><font color='green'>* 1 kernel space user space</font></i>
<a name='L138'><i><font color='green'>* 2 kernel space kernel space</font></i>
<a name='L139'><i><font color='green'>*</font></i>
<a name='L140'><i><font color='green'>* We do this by playing games with the fs segment register. Since it</font></i>
<a name='L141'><i><font color='green'>* it is expensive to load a segment register, we try to avoid calling</font></i>
<a name='L142'><i><font color='green'>* set_fs() unless we absolutely have to.</font></i>
<a name='L143'><i><font color='green'>*/</font></i>
<a name='L144'><i><font color='green'>/*</font></i>
<a name='L145'><i><font color='green'>* 'copy_string()'函数从用户内存空间拷贝参数和环境字符串到内核空闲页面内存中。</font></i>
<a name='L146'><i><font color='green'>* 这些已具有直接放到新用户内存中的格式。</font></i>
<a name='L147'><i><font color='green'>*</font></i>
<a name='L148'><i><font color='green'>* 由TYT(Tytso)于1991.12.24 日修改,增加了from_kmem 参数,该参数指明了字符串或</font></i>
<a name='L149'><i><font color='green'>* 字符串数组是来自用户段还是内核段。</font></i>
<a name='L150'><i><font color='green'>*</font></i>
<a name='L151'><i><font color='green'>* from_kmem argv * argv **</font></i>
<a name='L152'><i><font color='green'>* 0 用户空间 用户空间</font></i>
<a name='L153'><i><font color='green'>* 1 内核空间 用户空间</font></i>
<a name='L154'><i><font color='green'>* 2 内核空间 内核空间</font></i>
<a name='L155'><i><font color='green'>*</font></i>
<a name='L156'><i><font color='green'>* 我们是通过巧妙处理fs 段寄存器来操作的。由于加载一个段寄存器代价太大,所以</font></i>
<a name='L157'><i><font color='green'>* 我们尽量避免调用set_fs(),除非实在必要。</font></i>
<a name='L158'><i><font color='green'>*/</font></i>
<a name='L159'><i><font color='green'>//// 复制指定个数的参数字符串到参数和环境空间。</font></i>
<a name='L160'><i><font color='green'>// 参数:argc - 欲添加的参数个数;argv - 参数指针数组;page - 参数和环境空间页面指针数组。</font></i>
<a name='L161'><i><font color='green'>// p -在参数表空间中的偏移指针,始终指向已复制串的头部;from_kmem - 字符串来源标志。</font></i>
<a name='L162'><i><font color='green'>// 在do_execve()函数中,p 初始化为指向参数表(128kB)空间的最后一个长字处,参数字符串</font></i>
<a name='L163'><i><font color='green'>// 是以堆栈操作方式逆向往其中复制存放的,因此p 指针会始终指向参数字符串的头部。</font></i>
<a name='L164'><i><font color='green'>// 返回:参数和环境空间当前头部指针。</font></i>
<a name='L165'><b>static</b> <b>unsigned</b> <b>long</b>
<a name='L166'><a href='../R/412.html' title='Multiple refered from 7 places.'>copy_strings</a> (<b>int</b> argc, <b>char</b> **argv, <b>unsigned</b> <b>long</b> *page,
<a name='L167'> <b>unsigned</b> <b>long</b> p, <b>int</b> from_kmem)
<a name='L168'><font color='red'>{</font>
<a name='L169'> <b>char</b> *tmp, *pag;
<a name='L170'> <b>int</b> len, offset = 0;
<a name='L171'> <b>unsigned</b> <b>long</b> old_fs, new_fs;
<a name='L172'>
<a name='L173'> <b>if</b> (!p)
<a name='L174'> <b>return</b> 0; <i><font color='green'>/* bullet-proofing */</font></i><i><font color='green'>/* 偏移指针验证 */</font></i>
<a name='L175'><i><font color='green'>// 取ds 寄存器值到new_fs,并保存原fs 寄存器值到old_fs。</font></i>
<a name='L176'> new_fs = <a href='../S/24.html#L93' title='Defined at 93 in include/asm/segment.h.'>get_ds</a> ();
<a name='L177'> old_fs = <a href='../S/24.html#L83' title='Defined at 83 in include/asm/segment.h.'>get_fs</a> ();
<a name='L178'><i><font color='green'>// 如果字符串和字符串数组来自内核空间,则设置fs 段寄存器指向内核数据段(ds)。</font></i>
<a name='L179'> <b>if</b> (from_kmem == 2)
<a name='L180'> <a href='../S/24.html#L103' title='Defined at 103 in include/asm/segment.h.'>set_fs</a> (new_fs);
<a name='L181'><i><font color='green'>// 循环处理各个参数,从最后一个参数逆向开始复制,复制到指定偏移地址处。</font></i>
<a name='L182'> <b>while</b> (argc-- > 0)
<a name='L183'> <font color='red'>{</font>
<a name='L184'><i><font color='green'>// 如果字符串在用户空间而字符串数组在内核空间,则设置fs 段寄存器指向内核数据段(ds)。</font></i>
<a name='L185'> <b>if</b> (from_kmem == 1)
<a name='L186'> <a href='../S/24.html#L103' title='Defined at 103 in include/asm/segment.h.'>set_fs</a> (new_fs);
<a name='L187'><i><font color='green'>// 从最后一个参数开始逆向操作,取fs 段中最后一参数指针到tmp,如果为空,则出错死机。</font></i>
<a name='L188'> <b>if</b> (!(tmp = (<b>char</b> *) <a href='../S/24.html#L32' title='Defined at 32 in include/asm/segment.h.'>get_fs_long</a> (((<b>unsigned</b> <b>long</b> *) argv) + argc)))
<a name='L189'> <a href='../S/72.html#L24' title='Defined at 24 in kernel/panic.c.'>panic</a> ("argc is wrong");
<a name='L190'><i><font color='green'>// 如果字符串在用户空间而字符串数组在内核空间,则恢复fs 段寄存器原值。</font></i>
<a name='L191'> <b>if</b> (from_kmem == 1)
<a name='L192'> <a href='../S/24.html#L103' title='Defined at 103 in include/asm/segment.h.'>set_fs</a> (old_fs);
<a name='L193'><i><font color='green'>// 计算该参数字符串长度len,并使tmp 指向该参数字符串末端。</font></i>
<a name='L194'> len = 0; <i><font color='green'>/* remember zero-padding */</font></i>
<a name='L195'> <b>do</b>
<a name='L196'> <font color='red'>{</font> <i><font color='green'>/* 我们知道串是以NULL 字节结尾的 */</font></i>
<a name='L197'> len++;
<a name='L198'> <font color='red'>}</font>
<a name='L199'> <b>while</b> (<a href='../D/821.html' title='Multiple defined in 2 places.'>get_fs_byte</a> (tmp++));
<a name='L200'><i><font color='green'>// 如果该字符串长度超过此时参数和环境空间中还剩余的空闲长度,则恢复fs 段寄存器并返回0。</font></i>
<a name='L201'> <b>if</b> (p - len < 0)
<a name='L202'> <font color='red'>{</font> <i><font color='green'>/* this shouldn't happen - 128kB */</font></i>
<a name='L203'> <a href='../S/24.html#L103' title='Defined at 103 in include/asm/segment.h.'>set_fs</a> (old_fs); <i><font color='green'>/* 不会发生-因为有128kB 的空间 */</font></i>
<a name='L204'> <b>return</b> 0;
<a name='L205'> <font color='red'>}</font>
<a name='L206'><i><font color='green'>// 复制fs 段中当前指定的参数字符串,是从该字符串尾逆向开始复制。</font></i>
<a name='L207'> <b>while</b> (len)
<a name='L208'> <font color='red'>{</font>
<a name='L209'> --p;
<a name='L210'> --tmp;
<a name='L211'> --len;
<a name='L212'><i><font color='green'>// 函数刚开始执行时,偏移变量offset 被初始化为0,因此若offset-1<0,说明是首次复制字符串,</font></i>
<a name='L213'><i><font color='green'>// 则令其等于p 指针在页面内的偏移值,并申请空闲页面。</font></i>
<a name='L214'> <b>if</b> (--offset < 0)
<a name='L215'> <font color='red'>{</font>
<a name='L216'> offset = p % <a href='../D/324.html' title='Multiple defined in 4 places.'>PAGE_SIZE</a>;
<a name='L217'><i><font color='green'>// 如果字符串和字符串数组在内核空间,则恢复fs 段寄存器原值。</font></i>
<a name='L218'> <b>if</b> (from_kmem == 2)
<a name='L219'> <a href='../S/24.html#L103' title='Defined at 103 in include/asm/segment.h.'>set_fs</a> (old_fs);
<a name='L220'><i><font color='green'>// 如果当前偏移值p 所在的串空间页面指针数组项page[p/PAGE_SIZE]==0,表示相应页面还不存在,</font></i>
<a name='L221'><i><font color='green'>// 则需申请新的内存空闲页面,将该页面指针填入指针数组,并且也使pag 指向该新页面,若申请不</font></i>
<a name='L222'><i><font color='green'>// 到空闲页面则返回0。</font></i>
<a name='L223'> <b>if</b> (!(pag = (<b>char</b> *) page[p / <a href='../D/324.html' title='Multiple defined in 4 places.'>PAGE_SIZE</a>]) &&
<a name='L224'> !(pag = (<b>char</b> *) page[p / <a href='../D/324.html' title='Multiple defined in 4 places.'>PAGE_SIZE</a>] =
<a name='L225'> (<b>unsigned</b> <b>long</b> *) <a href='../S/94.html#L101' title='Defined at 101 in mm/memory.c.'>get_free_page</a> ()))
<a name='L226'> <b>return</b> 0;
<a name='L227'><i><font color='green'>// 如果字符串和字符串数组来自内核空间,则设置fs 段寄存器指向内核数据段(ds)。</font></i>
<a name='L228'> <b>if</b> (from_kmem == 2)
<a name='L229'> <a href='../S/24.html#L103' title='Defined at 103 in include/asm/segment.h.'>set_fs</a> (new_fs);
<a name='L230'>
<a name='L231'> <font color='red'>}</font>
<a name='L232'><i><font color='green'>// 从fs 段中复制参数字符串中一字节到pag+offset 处。</font></i>
<a name='L233'> *(pag + offset) = <a href='../D/821.html' title='Multiple defined in 2 places.'>get_fs_byte</a> (tmp);
<a name='L234'> <font color='red'>}</font>
<a name='L235'> <font color='red'>}</font>
<a name='L236'><i><font color='green'>// 如果字符串和字符串数组在内核空间,则恢复fs 段寄存器原值。</font></i>
<a name='L237'> <b>if</b> (from_kmem == 2)
<a name='L238'> <a href='../S/24.html#L103' title='Defined at 103 in include/asm/segment.h.'>set_fs</a> (old_fs);
<a name='L239'><i><font color='green'>// 最后,返回参数和环境空间中已复制参数信息的头部偏移值。</font></i>
<a name='L240'> <b>return</b> p;
<a name='L241'><font color='red'>}</font>
<a name='L242'>
<a name='L243'><i><font color='green'>//// 修改局部描述符表中的描述符基址和段限长,并将参数和环境空间页面放置在数据段末端。</font></i>
<a name='L244'><i><font color='green'>// 参数:text_size - 执行文件头部中a_text 字段给出的代码段长度值;</font></i>
<a name='L245'><i><font color='green'>// page - 参数和环境空间页面指针数组。</font></i>
<a name='L246'><i><font color='green'>// 返回:数据段限长值(64MB)。</font></i>
<a name='L247'><b>static</b> <b>unsigned</b> <b>long</b>
<a name='L248'><a href='../S/8.html#L518' title='Refered from 518 in fs/exec.c.'>change_ldt</a> (<b>unsigned</b> <b>long</b> text_size, <b>unsigned</b> <b>long</b> *page)
<a name='L249'><font color='red'>{</font>
<a name='L250'> <b>unsigned</b> <b>long</b> code_limit, data_limit, code_base, data_base;
<a name='L251'> <b>int</b> <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>;
<a name='L252'>
<a name='L253'><i><font color='green'>// 根据执行文件头部a_text 值,计算以页面长度为边界的代码段限长。并设置数据段长度为64MB。</font></i>
<a name='L254'> code_limit = text_size + <a href='../D/324.html' title='Multiple defined in 4 places.'>PAGE_SIZE</a> - 1;
<a name='L255'> code_limit &= 0xFFFFF000;
<a name='L256'> data_limit = 0x4000000;
<a name='L257'><i><font color='green'>// 取当前进程中局部描述符表代码段描述符中代码段基址,代码段基址与数据段基址相同。</font></i>
<a name='L258'> code_base = <a href='../S/36.html#L343' title='Defined at 343 in include/linux/sched.h.'>get_base</a> (current->ldt[1]);
<a name='L259'> data_base = code_base;
<a name='L260'><i><font color='green'>// 重新设置局部表中代码段和数据段描述符的基址和段限长。</font></i>
<a name='L261'> <a href='../S/36.html#L325' title='Defined at 325 in include/linux/sched.h.'>set_base</a> (current->ldt[1], code_base);
<a name='L262'> <a href='../S/36.html#L327' title='Defined at 327 in include/linux/sched.h.'>set_limit</a> (current->ldt[1], code_limit);
<a name='L263'> <a href='../S/36.html#L325' title='Defined at 325 in include/linux/sched.h.'>set_base</a> (current->ldt[2], data_base);
<a name='L264'> <a href='../S/36.html#L327' title='Defined at 327 in include/linux/sched.h.'>set_limit</a> (current->ldt[2], data_limit);
<a name='L265'><i><font color='green'>/* make sure fs points to the NEW data segment */</font></i>
<a name='L266'><i><font color='green'>/* 要确信fs 段寄存器已指向新的数据段 */</font></i>
<a name='L267'><i><font color='green'>// fs 段寄存器中放入局部表数据段描述符的选择符(0x17)。</font></i>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?