����12-14 linux/fs/exec.c


  1 /*

  2  *  linux/fs/exec.c

  3  *

  4  *  (C) 1991  Linus Torvalds

  5  */

  6

  7 /*

  8  * #!-checking implemented by tytso.

  9  */

    /*

     * #!��ʼ�Ľű�����ļ����벿������tytsoʵ�ֵġ�

     */

 10

 11 /*

 12  * Demand-loading implemented 01.12.91 - no need to read anything but

 13  * the header into memory. The inode of the executable is put into

 14  * "current->executable", and page faults do the actual loading. Clean.

 15  *

 16  * Once more I can proudly say that linux stood up to being changed: it

 17  * was less than 2 hours work to get demand-loading completely implemented.

 18  */

    /*

     * ����ʱ����ʵ����1991.12.1 - ֻ�轫ִ���ļ�ͷ�������ڴ�����뽫����

     * ִ���ļ������ؽ��ڴ档ִ���ļ���i�ڵ㱻���ڵ�ǰ���̵Ŀ�ִ���ֶ���

     * "current->executable"��ҳ�쳣�����ִ���ļ���ʵ�ʼ��ز��������������

     *

     * �ҿ�����һ���Ժ���˵��linux�������޸ģ�ֻ���˲���2Сʱ�Ĺ���ʱ���

     * ��ȫʵ����������ش�����

     */

 19

 20 #include <signal.h>       // �ź�ͷ�ļ��������źŷ��ų������źŽṹ���źŲ�������ԭ�͡�

 21 #include <errno.h>        // �����ͷ�ļ�������ϵͳ�и��ֳ����š�

 22 #include <string.h>       // �ַ���ͷ�ļ�����Ҫ������һЩ�й��ַ���������Ƕ�뺯����

 23 #include <sys/stat.h>     // �ļ�״̬ͷ�ļ��������ļ�״̬�ṹstat{}�ͷ��ų����ȡ�

 24 #include <a.out.h>        // a.outͷ�ļ���������a.outִ���ļ���ʽ��һЩ�ꡣ

 25

 26 #include <linux/fs.h>     // �ļ�ϵͳͷ�ļ��������ļ����ṹ��file��m_inode���ȡ�

 27 #include <linux/sched.h>  // ���ȳ���ͷ�ļ�������������ṹtask_struct������0���ݵȡ�

 28 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣

 29 #include <linux/mm.h>     // �ڴ����ͷ�ļ�������ҳ���С�����һЩҳ���ͷź���ԭ�͡�

 30 #include <asm/segment.h>  // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����

 31

 32 extern int sys_exit(int exit_code);     // �˳�����ϵͳ���á�

 33 extern int sys_close(int fd);           // �ر��ļ�ϵͳ���á�

 34

 35 /*

 36  * MAX_ARG_PAGES defines the number of pages allocated for arguments

 37  * and envelope for the new program. 32 should suffice, this gives

 38  * a maximum env+arg of 128kB !

 39  */

    /*

     * MAX_ARG_PAGES������Ϊ�³������ĸ������ͻ�������ʹ�õ�����ڴ�ҳ����

     * 32ҳ�ڴ�Ӧ���㹻�ˣ���ʹ�û����Ͳ�����env+arg���ռ���ܺʹﵽ128kB!

     */

 

 40 #define MAX_ARG_PAGES 32

 41

    //// ʹ�ÿ��ļ�ϵͳ���á�

    // ������library - ���ļ�����

    // Ϊ����ѡ��һ�����ļ������滻���̵�ǰ���ļ�i�ڵ��ֶ�ֵΪ����ָ�����ļ�����i�ڵ�

    // ָ�롣���libraryָ��Ϊ�գ���ѽ��̵�ǰ�Ŀ��ļ��ͷŵ���

    // ���أ��ɹ�����0�����򷵻س����롣

 42 int sys_uselib(const char * library)

 43 {

 44         struct m_inode * inode;

 45         unsigned long base;

 46

    // �����жϵ�ǰ�����Ƿ���ͨ���̡�����ͨ���鿴��ǰ���̵Ŀռ䳤���������ġ���Ϊ��ͨ��

    // �̵Ŀռ䳤�ȱ�����ΪTASK_SIZE��64MB��������������߼���ַ�ռ䳤�Ȳ�����TASK_SIZE

    // �򷵻س����루��Ч������������ȡ���ļ�i�ڵ�inode�������ļ���ָ��գ�������inode

    // ����NULL��

 47         if (get_limit(0x17) != TASK_SIZE)

 48                 return -EINVAL;

 49         if (library) {

 50                 if (!(inode=namei(library)))            /* get library inode */

 51                         return -ENOENT;                 /* ȡ���ļ�i�ڵ� */

 52         } else

 53                 inode = NULL;

 54 /* we should check filetypes (headers etc), but we don't */

    /* ����Ӧ�ü��һ���ļ����ͣ���ͷ����Ϣ�ȣ����������ǻ�û���������� */

    // Ȼ��Żؽ���ԭ���ļ�i�ڵ㣬��Ԥ�ý��̿�i�ڵ��ֶ�Ϊ�ա�����ȡ�ý��̵Ŀ��������

    // λ�ã����ͷ�ԭ������ҳ������ռ�õ��ڴ�ҳ�档����ý��̿�i�ڵ��ֶ�ָ���¿�i��

    // �㣬������0���ɹ�����

 55         iput(current->library);

 56         current->library = NULL;

 57         base = get_base(current->ldt[2]);

 58         base += LIBRARY_OFFSET;

 59         free_page_tables(base,LIBRARY_SIZE);

 60         current->library = inode;

 61         return 0;

 62 }

 63

 64 /*

 65  * create_tables() parses the env- and arg-strings in new user

 66  * memory and creates the pointer tables from them, and puts their

 67  * addresses on the "stack", returning the new stack pointer value.

 68  */

    /*

     * create_tables()�������������ڴ��н������������Ͳ����ַ������ɴ�

     * ����ָ������������ǵĵ�ַ�ŵ�"ջ"�ϣ�Ȼ�󷵻���ջ��ָ��ֵ��

     */

    //// ��������ջ�д��������ͻ�������ָ�����

    // ������p -���ݶ��в����ͻ�����Ϣƫ��ָ�룻argc - ����������envc - ��������������

    // ���أ�ջָ��ֵ��

 69 static unsigned long * create_tables(char * p,int argc,int envc)

 70 {

 71         unsigned long *argv,*envp;

 72         unsigned long * sp;

 73

    // ջָ������4�ֽڣ�1�ڣ�Ϊ�߽����Ѱַ�ģ������������ spΪ4��������ֵ����ʱsp

    // λ�ڲ�����������ĩ�ˡ�Ȼ�������Ȱ�sp ���£��͵�ַ�����ƶ�����ջ�пճ���������

    // ָ��ռ�õĿռ䣬���û�������ָ��envp ָ��ô�����ճ���һ��λ�������������һ

    // ��NULLֵ������ָ���1��sp������ָ������ֽ�ֵ��4�ֽڣ����ٰ�sp�����ƶ����ճ�

    // �����в���ָ��ռ�õĿռ䣬����argv ָ��ָ��ô���ͬ������մ���һ��λ�����ڴ��

    // һ��NULLֵ����ʱspָ�����ָ������ʼ�������ǽ�����������ָ��envp�������в�

    // ����ָ���Լ������в�������ֵ�ֱ�ѹ��ջ�С�

 74         sp = (unsigned long *) (0xfffffffc & (unsigned long) p);

 75         sp -= envc+1;                              // ��sp = sp - (envc+1);

 76         envp = sp;

 77         sp -= argc+1;

 78         argv = sp;

 79         put_fs_long((unsigned long)envp,--sp);

 80         put_fs_long((unsigned long)argv,--sp);

 81         put_fs_long((unsigned long)argc,--sp);

    // �ٽ������и�����ָ��ͻ���������ָ��ֱ����ǰ��ճ�������Ӧ�ط������ֱ����һ

    // ��NULLָ�롣

 82         while (argc-->0) {

 83                 put_fs_long((unsigned long) p,argv++);

 84                 while (get_fs_byte(p++)) /* nothing */ ; // pָ��ָ����һ����������

 85         }

 86         put_fs_long(0,argv);

 87         while (envc-->0) {

 88                 put_fs_long((unsigned long) p,envp++);

 89                 while (get_fs_byte(p++)) /* nothing */ ; // pָ��ָ����һ����������

 90         }

 91         put_fs_long(0,envp);

 92         return sp;                         // ���ع���ĵ�ǰ��ջָ�롣

 93 }

 94

 95 /*

 96  * count() counts the number of arguments/envelopes

 97  */

    /*

     * count()�������������в���/���������ĸ�����

     */

    //// �������������

    // ������argv - ����ָ�����飬���һ��ָ������NULL��

    // ͳ�Ʋ���ָ��������ָ��ĸ��������ں�����������ָ���ָ������ã���μ�����

    // kernel/sched.c�е�171��ǰ��ע�͡�

    // ���أ�����������

 98 static int count(char ** argv)

 99 {

100         int i=0;

101         char ** tmp;

102

103         if (tmp = argv)

104                 while (get_fs_long((unsigned long *) (tmp++)))

105                         i++;

106

107         return i;

108 }

109

110 /*

111  * 'copy_string()' copies argument/envelope strings from user

112  * memory to free pages in kernel mem. These are in a format ready

113  * to be put directly into the top of new user memory.

114  *

115  * Modified by TYT, 11/24/91 to add the from_kmem argument, which specifies

116  * whether the string and the string array are from user or kernel segments:

117  *

118  * from_kmem     argv *        argv **

119  *    0          user space    user space

120  *    1          kernel space  user space

121  *    2          kernel space  kernel space

122  *

123  * We do this by playing games with the fs segment register.  Since it

124  * it is expensive to load a segment register, we try to avoid calling

125  * set_fs() unless we absolutely have to.

126  */

    /*

     * 'copy_string()'�������û��ڴ�ռ俽������/�����ַ������ں˿���ҳ���С�

     * ��Щ�Ѿ���ֱ�ӷŵ����û��ڴ��еĸ�ʽ��

     *

     * ��TYT(Tytso)��1991.11.24���޸ģ�������from_kmem�������ò���ָ����

     * �ַ������ַ��������������û��λ����ں˶Ρ�

     *

     * from_kmem   ָ��argv *    �ַ��� argv **

     *    0         �û��ռ�      �û��ռ�

     *    1         �ں˿ռ�      �û��ռ�

     *    2         �ں˿ռ�      �ں˿ռ�

     *

     * ������ͨ�������fs�μĴ����������ġ����ڼ���һ���μĴ�������̫�ߣ�

     * �������Ǿ����������set_fs()������ʵ�ڱ�Ҫ��

     */

    //// ����ָ�������IJ����ַ����������ͻ����ռ��С�

    // ������argc - �����ӵIJ���������argv - ����ָ�����飻page - �����ͻ����ռ�ҳ��ָ��

    // ���顣p -�������ռ���ƫ��ָ�룬ʼ��ָ���Ѹ��ƴ���ͷ����from_kmem -�ַ�����Դ��־��

    // �� do_execve()�����У�p��ʼ��Ϊָ�������(128kB)�ռ�����һ�����ִ��������ַ���

    // ���Զ�ջ������ʽ���������и��ƴ�ŵġ���� pָ������Ÿ�����Ϣ�����Ӷ��𽥼�С��

    // ��ʼ��ָ������ַ�����ͷ�����ַ�����Դ��־from_kmemӦ����TYTΪ�˸�execve()����

    // ִ�нű��ļ��Ĺ��ܶ��¼ӵIJ�������û�����нű��ļ��Ĺ���ʱ�����в����ַ���������

    // �����ݿռ��С�

    // ���أ������ͻ����ռ䵱ǰͷ��ָ�롣�������򷵻�0��

127 static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,

128                 unsigned long p, int from_kmem)

129 {

130         char *tmp, *pag;

131         int len, offset = 0;

132         unsigned long old_fs, new_fs;

133

    // ����ȡ��ǰ�μĴ���ds��ָ���ں����ݶΣ���fsֵ���ֱ𱣴浽����new_fs��old_fs�С�

    // ����ַ������ַ������飨ָ�룩�����ں˿ռ䣬������fs�μĴ���ָ���ں����ݶΡ�

134         if (!p)

135                 return 0;       /* bullet-proofing */  /* ƫ��ָ����֤ */

136         new_fs = get_ds();

137         old_fs = get_fs();

138         if (from_kmem==2)           // ��������ָ�����ں˿ռ�������fsָ���ں˿ռ䡣

139                 set_fs(new_fs);

    // Ȼ��ѭ���������������������һ����������ʼ���ƣ����Ƶ�ָ��ƫ�Ƶ�ַ������ѭ���У�

    // ����ȡ��Ҫ���Ƶĵ�ǰ�ַ���ָ�롣����ַ������û��ռ���ַ������飨�ַ���ָ�룩��

    // �ں˿ռ䣬������fs�μĴ���ָ���ں����ݶΣ�ds���������ں����ݿռ���ȡ���ַ���ָ��

    // tmp֮������ָ̻�fs�μĴ���ԭֵ��fs��ָ���û��ռ䣩���������޸�fsֵ��ֱ�Ӵ�

    // �û��ռ�ȡ�ַ���ָ�뵽tmp��

140         while (argc-- > 0) {

141                 if (from_kmem == 1)      // ����ָ�����ں˿ռ䣬��fsָ���ں˿ռ䡣

142                         set_fs(new_fs);

143                 if (!(tmp = (char *)get_fs_long(((unsigned long *)argv)+argc)))

144                         panic("argc is wrong");

145                 if (from_kmem == 1)      // ����ָ�����ں˿ռ䣬��fsָ���û��ռ䡣

146                         set_fs(old_fs);

    // Ȼ����û��ռ�ȡ���ַ�����������ò����ַ�������len�� �˺�tmpָ����ַ���ĩ�ˡ�

    // ������ַ������ȳ�����ʱ�����ͻ����ռ��л�ʣ��Ŀ��г��ȣ���ռ䲻���ˡ����ǻָ�

    // fs�μĴ���ֵ��������ı�Ļ���������0��������Ϊ�����ͻ����ռ�����128KB������ͨ

    // �������ܷ������������

147                 len=0;                         /* remember zero-padding */

148                 do {                           /* ����֪��������NULL�ֽڽ�β�� */

149                         len++;

150                 } while (get_fs_byte(tmp++));

151                 if (p-len < 0) {               /* this shouldn't happen - 128kB */

152                         set_fs(old_fs);        /* ���ᷢ��-��Ϊ��128kB�Ŀռ� */

153                         return 0;

154                 }

    // ����������������ַ��ذ��ַ������Ƶ������ͻ����ռ�ĩ�˴�����ѭ�������ַ������ַ�

    // �����У���������Ҫ�жϲ����ͻ����ռ�����Ӧλ�ô��Ƿ��Ѿ����ڴ�ҳ�档�����û�о�

    // ��Ϊ������1ҳ�ڴ�ҳ�档ƫ����offset������Ϊ��һ��ҳ���еĵ�ǰָ��ƫ��ֵ�� ��Ϊ

    // �տ�ʼִ�б�����ʱ��ƫ�Ʊ���offset����ʼ��Ϊ0������(offset-1 < 0)�϶�������ʹ��

    // offset���±�����Ϊ��ǰpָ����ҳ�淶Χ�ڵ�ƫ��ֵ��

155                 while (len) {

156                         --p; --tmp; --len;

157                         if (--offset < 0) {

158                                 offset = p % PAGE_SIZE;

159                                 if (from_kmem==2) // �������ں˿ռ���fsָ���û��ռ䡣

160                                         set_fs(old_fs);

    // �����ǰƫ��ֵp���ڵĴ��ռ�ҳ��ָ�������� page[p/PAGE_SIZE] ==0����ʾ��ʱpָ��

    // �����Ŀռ��ڴ�ҳ�滹�����ڣ���������һ�����ڴ�ҳ��������ҳ��ָ������ָ�����飬ͬ

    // ʱҲʹҳ��ָ��pagָ�����ҳ�档�����벻������ҳ���򷵻�0��

161                                 if (!(pag = (char *) page[p/PAGE_SIZE]) &&

162                                     !(pag = (char *) page[p/PAGE_SIZE] =

163                                       (unsigned long *) get_free_page()))

164                                         return 0;

165                                 if (from_kmem==2) // �������ں˿ռ���fsָ���ں˿ռ䡣

166                                         set_fs(new_fs);

167

168                         }

    // Ȼ���fs���и����ַ�����1�ֽڵ������ͻ����ռ��ڴ�ҳ��pag��offset����

169                         *(pag + offset) = get_fs_byte(tmp);

170                 }

171         }

    // ����ַ������ַ����������ں˿ռ䣬��ָ�fs�μĴ���ԭֵ����󣬷��ز����ͻ�����

    // �����Ѹ��Ʋ�����ͷ��ƫ��ֵ��

172         if (from_kmem==2)

173                 set_fs(old_fs);

174         return p;

175 }

176

    //// �޸�����ľֲ������������ݡ�

    // �޸ľֲ���������LDT���������Ķλ�ַ�Ͷ��޳������������ͻ����ռ�ҳ����������ݶ�

    // ĩ�ˡ�

    // ������text_size - ִ���ļ�ͷ����a_text�ֶθ����Ĵ���γ���ֵ��

    // page - �����ͻ����ռ�ҳ��ָ�����顣

    // ���أ����ݶ��޳�ֵ��64MB����

177 static unsigned long change_ldt(unsigned long text_size,unsigned long * page)

178 {

179         unsigned long code_limit,data_limit,code_base,data_base;

180         int i;

181

    // ���ȰѴ�������ݶγ��Ⱦ�����Ϊ64MB�� Ȼ��ȡ��ǰ���ֲ̾���������������������д�

    // ��λ�ַ������λ�ַ�����ݶλ�ַ��ͬ����ʹ����Щ��ֵ�������þֲ����д���κ�����

    // ���������еĻ�ַ�Ͷ��޳���������ע�⣬���ڱ����ص��³���Ĵ�������ݶλ�ַ��ԭ��

    // �����ͬ�����û�б�Ҫ���ظ�ȥ�������ǣ�����186��188���ϵ��������öλ�ַ�����

    // ���࣬��ʡ�ԡ�

182         code_limit = TASK_SIZE;

183         data_limit = TASK_SIZE;

184         code_base = get_base(current->ldt[1]);  // include/linux/sched.h����226�С�

185         data_base = code_base;

186         set_base(current->ldt[1],code_base);

187         set_limit(current->ldt[1],code_limit);

188         set_base(current->ldt[2],data_base);

189         set_limit(current->ldt[2],data_limit);

190 /* make sure fs points to the NEW data segment */

    /* Ҫȷ��fs�μĴ�����ָ���µ����ݶ� */

    // fs�μĴ����з���ֲ������ݶ���������ѡ���(0x17)����Ĭ�������fs��ָ���������ݶΡ�

191         __asm__("pushl $0x17\n\tpop %%fs"::);

    // Ȼ�󽫲����ͻ����ռ��Ѵ�����ݵ�ҳ�棨�����MAX_ARG_PAGESҳ��128kB���ŵ����ݶ�ĩ

    // �ˡ� �����Ǵӽ��̿ռ�����λ�ÿ�ʼ������һҳһҳ�طš����ļ�����ռ�ý��̿ռ����

    // 4MB������put_dirty_page()���ڰ�����ҳ��ӳ�䵽�����߼��ռ��С���mm/memory.c�С�

192         data_base += data_limit - LIBRARY_SIZE;

193         for (i=MAX_ARG_PAGES-1 ; i>=0 ; i--) {

194                 data_base -= PAGE_SIZE;

195                 if (page[i])                           // ����ҳ����ڣ��ͷ��ø�ҳ�档

196                         put_dirty_page(page[i],data_base);

197         }

198         return data_limit;                             // ��󷵻����ݶ��޳���64MB����

199 }

200

201 /*

202  * 'do_execve()' executes a new program.

203  *

204  * NOTE! We leave 4MB free at the top of the data-area for a loadable

205  * library.

206  */

    /*

     * 'do_execve()'����ִ��һ���³���

     */

    //// execve()ϵͳ�жϵ��ú��������ز�ִ���ӽ��̣��������򣩡�

    // �ú�����ϵͳ�жϵ��ã�int 0x80�����ܺ�__NR_execve���õĺ����������IJ����ǽ���ϵͳ

    // ���ô������̺�ֱ�����ñ�ϵͳ���ô������̣�system_call.s��200�У��͵��ñ�����֮ǰ

    // ��system_call.s����203�У���ѹ��ջ�е�ֵ����Щֵ������

    // �� ��86--88����ѵ�edx��ecx��ebx�Ĵ���ֵ���ֱ��Ӧ**envp��**argv��*filename��

    // �� ��94�е���sys_call_table��sys_execve������ָ�룩ʱѹ��ջ�ĺ������ص�ַ��tmp����

    // �� ��202���ڵ��ñ�����do_execveǰ��ջ��ָ��ջ�е���ϵͳ�жϵij������ָ��eip��

    // ������

    // eip - ����ϵͳ�жϵij������ָ�룬�μ�kernel/system_call.s����ʼ���ֵ�˵����

    // tmp - ϵͳ�ж����ڵ���_sys_execveʱ�ķ��ص�ַ�����ã�

    // filename - ��ִ�г����ļ���ָ�룻

    // argv - �����в���ָ�������ָ�룻

    // envp - ��������ָ�������ָ�롣

    // ���أ�������óɹ����򲻷��أ��������ó����ţ�������-1��

207 int do_execve(unsigned long * eip,long tmp,char * filename,

208         char ** argv, char ** envp)

209 {

210         struct m_inode * inode;

211         struct buffer_head * bh;

212         struct exec ex;

213         unsigned long page[MAX_ARG_PAGES];         // �����ͻ������ռ�ҳ��ָ�����顣

214         int i,argc,envc;

215         int e_uid, e_gid;                          // ��Ч�û�ID����Ч��ID��

216         int retval;

217         int sh_bang = 0;                           // �����Ƿ���Ҫִ�нű�����

218         unsigned long p=PAGE_SIZE*MAX_ARG_PAGES-4; // pָ������ͻ����ռ����󲿡�

219

    // ����ʽ����ִ���ļ������л���֮ǰ���������ȸ�Щ���¡��ں�׼����128KB��32��ҳ�棩

    // �ռ�����Ż�ִ���ļ��������в����ͻ����ַ��������а�p��ʼ���ó�λ��128KB�ռ��

    // ���1�����ִ����ڳ�ʼ�����ͻ����ռ�IJ��������У�p������ָ����128KB�ռ��еĵ�

    // ǰλ�á�

    // ���⣬����eip[1]�ǵ��ñ���ϵͳ���õ�ԭ�û��������μĴ���CSֵ�����еĶ�ѡ���

    // ��Ȼ�����ǵ�ǰ����Ĵ����ѡ�����0x000f���������Ǹ�ֵ����ô CSֻ�ܻ����ں˴���

    // �ε�ѡ��� 0x0008�� �����Ǿ��Բ������ģ���Ϊ�ں˴����dz�פ�ڴ�����ܱ��滻���ġ�

    // ����������eip[1] ��ֵȷ���Ƿ�������������Ȼ���ٳ�ʼ��128KB�IJ����ͻ�������

    // �䣬�������ֽ����㣬��ȡ��ִ���ļ���i�ڵ㡣�ٸ��ݺ��������ֱ����������в�����

    // �����ַ����ĸ���argc��envc�����⣬ִ���ļ������dz����ļ���

220         if ((0xffff & eip[1]) != 0x000f)

221                 panic("execve called from supervisor mode");

222         for (i=0 ; i<MAX_ARG_PAGES ; i++)       /* clear page-table */

223                 page[i]=0;

224         if (!(inode=namei(filename)))           /* get executables inode */

225                 return -ENOENT;

226         argc = count(argv);                     // �����в���������

227         envc = count(envp);                     // �����ַ�������������

228        

229 restart_interp:

230         if (!S_ISREG(inode->i_mode)) {    /* must be regular file */

231                 retval = -EACCES;

232                 goto exec_error2;        //�����dz����ļ����ó����룬��ת��376�С�

233         }

    // �����鵱ǰ�����Ƿ���Ȩ����ָ����ִ���ļ���������ִ���ļ�i�ڵ��е����ԣ�������

    // �����Ƿ���Ȩִ�������ڰ�ִ���ļ�i�ڵ�������ֶ�ֵȡ��i�к��������Ȳ鿴������

    // �Ƿ������ˡ�����-�û�-ID����set-user_id����־ �͡�����-��-ID����set-group-id����

    // ־����������־��Ҫ����һ���û��ܹ�ִ����Ȩ�û����糬���û�root���ij�������ı�

    // ����ij���passwd�ȡ����set-user-id��־��λ�������ִ�н��̵���Ч�û�ID��euid��

    // �����ó�ִ���ļ����û�ID���������óɵ�ǰ���̵�euid�����ִ���ļ�set-group-id��

    // ��λ�Ļ�����ִ�н��̵���Ч��ID��egid��������Ϊִ���ļ�����ID���������óɵ�ǰ����

    // ��egid��������ʱ���������жϳ�����ֵ�����ڱ���e_uid��e_gid�С�

234         i = inode->i_mode;

235         e_uid = (i & S_ISUID) ? inode->i_uid : current->euid;

236         e_gid = (i & S_ISGID) ? inode->i_gid : current->egid;

 

    // ���ڸ��ݽ��̵�euid��egid��ִ���ļ��ķ������Խ��бȽϡ����ִ���ļ��������н���

    // ���û�������ļ�����ֵi����6λ����ʱ�����3λ���ļ������ķ���Ȩ�ޱ�־�������

    // �����ִ���ļ��뵱ǰ���̵��û�����ͬ�飬��ʹ����ֵ���3λ��ִ���ļ����û��ķ���

    // Ȩ�ޱ�־�������ʱ���������3λ���������û����ʸ�ִ���ļ���Ȩ�ޡ�

    // Ȼ�����Ǹ���������i�����3����ֵ���жϵ�ǰ�����Ƿ���Ȩ���������ִ���ļ������

    // ѡ������Ӧ�û�û�����и��ļ���Ȩ����λ0��ִ��Ȩ�ޣ������������û�Ҳû���κ�Ȩ��

    // ���ߵ�ǰ�����û����dz����û����������ǰ����û��Ȩ���������ִ���ļ��������ò���

    // ִ�г����룬����ת��exec_error2��ȥ���˳�������

237         if (current->euid == inode->i_uid)

238                 i >>= 6;

239         else if (in_group_p(inode->i_gid))

240                 i >>= 3;

241         if (!(i & 1) &&

242             !((inode->i_mode & 0111) && suser())) {

243                 retval = -ENOEXEC;

244                 goto exec_error2;

245         }

    // ����ִ�е����˵����ǰ����������ָ��ִ���ļ���Ȩ�ޡ���˴����↑ʼ������Ҫȡ��

    // ִ���ļ�ͷ�����ݲ��������е���Ϣ�������������л���������������һ��shell������ִ

    // �нű��������ȶ�ȡִ���ļ���1�����ݵ����ٻ�����С� �����ƻ�������ݵ�ex�С�

    // ���ִ���ļ���ʼ�������ֽ����ַ�'#!'����˵��ִ���ļ���һ���ű��ı��ļ����������

    // �нű��ļ������Ǿ���Ҫִ�нű��ļ��Ľ��ͳ�������shell���򣩡�ͨ���ű��ļ��ĵ�

    // һ���ı�Ϊ��#��/bin/bash������ָ�������нű��ļ���Ҫ�Ľ��ͳ������з����Ǵӽű�

    // �ļ���1�У����ַ�'#!'����ȡ�����еĽ��ͳ�����������IJ��������еĻ�����Ȼ����

    // Щ�����ͽű��ļ����Ž�ִ���ļ�����ʱ�ǽ��ͳ��򣩵������в����ռ��С�����֮ǰ����

    // ��Ȼ��Ҫ�ȰѺ���ָ����ԭ�������в����ͻ����ַ����ŵ�128KB�ռ��У������ィ������

    // �������в�����ŵ�����ǰ��λ�ô�����Ϊ��������ã���������ں�ִ�нű��ļ��Ľ���

    // ����������������úý��ͳ���Ľű��ļ����Ȳ�����ȡ�����ͳ����i�ڵ㲢��ת��

    // 229��ȥִ�н��ͳ�������������Ҫ��ת��ִ�й��Ĵ���229��ȥ�����������ȷ�ϲ���

    // ���˽ű��ļ�֮����Ҫ����һ����ֹ�ٴ�ִ������Ľű����������־sh_bang ���ں����

    // �����иñ�־Ҳ������ʾ�����Ѿ����ú�ִ���ļ��������в�������Ҫ�ظ����á�

246         if (!(bh = bread(inode->i_dev,inode->i_zone[0]))) {

247                 retval = -EACCES;

248                 goto exec_error2;

249         }

250         ex = *((struct exec *) bh->b_data);     /* read exec-header */

251         if ((bh->b_data[0] == '#') && (bh->b_data[1] == '!') && (!sh_bang)) {

252                 /*

253                  * This section does the #! interpretation.

254                  * Sorta complicated, but hopefully it will work.  -TYT

255                  */

                    /*

                     * �ⲿ�ִ�����'#!'�Ľ��ͣ���Щ���ӣ���ϣ���ܹ�����-TYT

                     */

256

257                 char buf[128], *cp, *interp, *i_name, *i_arg;

258                 unsigned long old_fs;

259

    // �����↑ʼ�����Ǵӽű��ļ�����ȡ���ͳ�����������������ѽ��ͳ����������ͳ���IJ���

    // �ͽű��ļ�����Ϸ��뻷���������С����ȸ��ƽű��ļ�ͷ1���ַ�'#!'������ַ�����buf

    // �У����к��нű����ͳ�����������/bin/sh����Ҳ���ܻ��������ͳ���ļ���������Ȼ���

    // buf�е����ݽ��д�����ɾ����ʼ�Ŀո��Ʊ�����

260                 strncpy(buf, bh->b_data+2, 127);

261                 brelse(bh);

262                 iput(inode);                     // �ͷŻ���鲢�Żؽű��ļ�i�ڵ㡣

263                 buf[127] = '\0';

264                 if (cp = strchr(buf, '\n')) {

265                         *cp = '\0';       // ��1�����з�����NULL��ȥ���ո��Ʊ�����

266                         for (cp = buf; (*cp == ' ') || (*cp == '\t'); cp++);

267                 }

268                 if (!cp || *cp == '\0') {        // ������û���������ݣ��������

269                         retval = -ENOEXEC;       /* No interpreter name found */

270                         goto exec_error1;        /* û���ҵ��ű����ͳ����� */

271                 }

    // ��ʱ���ǵõ��˿�ͷ�ǽű����ͳ�������һ�����ݣ��ַ�����������������С�����ȡ��һ��

    // �ַ�������Ӧ���ǽ��ͳ���������ʱi_nameָ������ơ������ͳ����������ַ���������Ӧ

    // ���ǽ��ͳ���IJ�������������i_argָ��ô���

272                 interp = i_name = cp;

273                 i_arg = 0;

274                 for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) {

275                         if (*cp == '/')

276                                 i_name = cp+1;

277                 }

278                 if (*cp) {

279                         *cp++ = '\0';            // ���ͳ�����β����NULL�ַ���

280                         i_arg = cp;              // i_argָ����ͳ��������

281                 }

282                 /*

283                  * OK, we've parsed out the interpreter name and

284                  * (optional) argument.

285                  */

                    /*

                     * OK�������Ѿ����������ͳ�����ļ����Լ�(��ѡ��)������

                     */

    // ��������Ҫ��������������Ľ��ͳ�����i_name �������i_arg �ͽű��ļ�����Ϊ���ͳ�

    // ��IJ����Ž������Ͳ������С���������������Ҫ�Ѻ����ṩ��ԭ��һЩ�����ͻ����ַ���

    // �ȷŽ�ȥ��Ȼ���ٷ�������������ġ�������������в�����˵�����ԭ���IJ�����"-arg1

    //  -arg2"�����ͳ�������"bash"���������"-iarg1 -iarg2"���ű��ļ�������ԭ����ִ����

    // ��������"example.sh"����ô�ڷ�������IJ���֮���µ�������������������

    //         ��bash -iarg1 -iarg2 example.sh -arg1 -arg2��

    // �������ǰ�sh_bang��־���ϣ�Ȼ��Ѻ��������ṩ��ԭ�в����ͻ����ַ������뵽�ռ��С�

    // �����ַ����Ͳ��������ֱ���envc ��argc-1�����ٸ��Ƶ�һ��ԭ�в�����ԭ����ִ���ļ�

    // ����������Ľű��ļ�����[[?? ���Կ�����ʵ�������Dz���Ҫȥ���д����ű��ļ���������

    // ����ȫ���Ը���argc������������ԭ��ִ���ļ����������ڵĽű��ļ���������Ϊ��λ��ͬ

    // һ��λ���� ]]��ע�⣡����ָ��p���Ÿ�����Ϣ���Ӷ�����С��ַ�����ƶ������������

    // ���ƴ�����ִ����󣬻�����������Ϣ��λ�ڳ��������в�������Ϣ����Ϸ������� pָ��

    // ����ĵ�1����������copy_strings()���һ��������0��ָ�������ַ������û��ռ䡣

286                 if (sh_bang++ == 0) {

287                         p = copy_strings(envc, envp, page, p, 0);

288                         p = copy_strings(--argc, argv+1, page, p, 0);

289                 }

290                 /*

291                  * Splice in (1) the interpreter's name for argv[0]

292                  *           (2) (optional) argument to interpreter

293                  *           (3) filename of shell script

294                  *

295                  * This is done in reverse order, because of how the

296                  * user environment and arguments are stored.

297                  */

                    /*

                     * ƴ�� (1) argv[0]�зŽ��ͳ��������

                     *      (2) (��ѡ��)���ͳ���IJ���

                     *      (3) �ű����������

                     *

                     * ������������д����ģ��������û������Ͳ����Ĵ�ŷ�ʽ��ɵġ�

                     */

    // �������������ƽű��ļ��������ͳ���IJ����ͽ��ͳ����ļ����������ͻ����ռ��С�

    // �����������ó����룬��ת��exec_error1�����⣬���ڱ����������ṩ�Ľű��ļ���

    // filename���û��ռ䣬�����︳��copy_strings()�Ľű��ļ�����ָ�����ں˿ռ䣬��

    // ����������ַ������������һ���������ַ�����Դ��־����Ҫ�����ó�1�����ַ�����

    // �ں˿ռ䣬��copy_strings()�����һ������Ҫ���ó�2��������ĵ�301��304�С�

298                 p = copy_strings(1, &filename, page, p, 1);

299                 argc++;

300                 if (i_arg) {                      // ���ƽ��ͳ���Ķ��������

301                         p = copy_strings(1, &i_arg, page, p, 2);

302                         argc++;

303                 }

304                 p = copy_strings(1, &i_name, page, p, 2);

305                 argc++;

306                 if (!p) {

307                         retval = -ENOMEM;

308                         goto exec_error1;

309                 }

310                 /*

311                  * OK, now restart the process with the interpreter's inode.

312                  */

                    /*

                     * OK������ʹ�ý��ͳ����i�ڵ��������̡�

                     */

    // �������ȡ�ý��ͳ����i�ڵ�ָ�룬Ȼ����ת��204��ȥִ�н��ͳ���Ϊ�˻�ý��ͳ�

    // ���i�ڵ㣬������Ҫʹ��namei()���������Ǹú�����ʹ�õIJ������ļ������Ǵ��û���

    // �ݿռ�õ��ģ����ӶμĴ���fs��ָ�ռ���ȡ�á�����ڵ���namei()����֮ǰ������Ҫ

    // ����ʱ��fsָ���ں����ݿռ䣬���ú����ܴ��ں˿ռ�õ����ͳ�����������namei()

    // ���غ�ָ�fs��Ĭ�����á����������������ʱ����ԭfs�μĴ�����ԭָ���û����ݶΣ�

    // ��ֵ���������ó�ָ���ں����ݶΣ�Ȼ��ȡ���ͳ����i�ڵ㡣֮���ٻָ�fs��ԭֵ����

    // ��ת��restart_interp��204�У������´����µ�ִ���ļ� -- �ű��ļ��Ľ��ͳ���

313                 old_fs = get_fs();

314                 set_fs(get_ds());

315                 if (!(inode=namei(interp))) {        /* get executables inode */

316                         set_fs(old_fs);              /* ȡ�ý��ͳ����i�ڵ� */

317                         retval = -ENOENT;

318                         goto exec_error1;

319                 }

320                 set_fs(old_fs);

321                 goto restart_interp;

322         }

 

    // ��ʱ������е�ִ���ļ�ͷ�ṹ�����Ѿ����Ƶ���ex �С� �������ͷŸû���飬����ʼ��

    // ex�е�ִ��ͷ��Ϣ�����жϴ���������Linux 0.12�ں���˵������֧��ZMAGICִ���ļ���

    // ʽ������ִ���ļ����붼���߼���ַ0 ��ʼִ�У���˲�֧�ֺ��д���������ض�λ��Ϣ��

    // ִ���ļ�����Ȼ�����ִ���ļ�ʵ��̫�����ִ���ļ���ȱ��ȫ����ô����Ҳ������������

    // ��˶��������������ִ�г������ִ���ļ���������ҳ��ִ���ļ���ZMAGIC�������ߴ�

    // ��������ض�λ���ֳ��Ȳ�����0������(�����+���ݶ�+��) ���ȳ���50MB������ִ���ļ�

    // ����С�� (�����+���ݶ�+���ű�����+ִ��ͷ����) ���ȵ��ܺ͡�

323         brelse(bh);

324         if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize ||

325                 ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||

326                 inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {

327                 retval = -ENOEXEC;

328                 goto exec_error2;

329         }

    // ���⣬���ִ���ļ��д��뿪ʼ��û��λ��1��ҳ�棨1024�ֽڣ��߽紦����Ҳ����ִ�С�

    // ��Ϊ����ҳ��Demand paging������Ҫ�����ִ���ļ�����ʱ��ҳ��Ϊ��λ�����Ҫ��ִ��

    // �ļ�ӳ���д�������ݶ���ҳ��߽紦��ʼ��

330         if (N_TXTOFF(ex) != BLOCK_SIZE) {

331                 printk("%s: N_TXTOFF != BLOCK_SIZE. See a.out.h.", filename);

332                 retval = -ENOEXEC;

333                 goto exec_error2;

334         }

    // ���sh_bang��־û�����ã�����ָ�������������в����ͻ����ַ����������ͻ����ռ�

    // �С���sh_bang��־�Ѿ����ã�������ǽ����нű����ͳ��򣬴�ʱ��������ҳ���Ѿ����ƣ�

    // �����ٸ��ơ�ͬ������sh_bangû����λ����Ҫ���ƵĻ�����ô��ʱָ��p���Ÿ�����Ϣ��

    // �Ӷ�����С��ַ�����ƶ���������������ƴ�����ִ����󣬻�����������Ϣ��λ�ڳ���

    // ��������Ϣ����Ϸ�������pָ�����ĵ�1������������ʵ�ϣ�p��128KB�����ͻ�����

    // ���е�ƫ��ֵ��������p=0�����ʾ��������������ռ�ҳ���Ѿ���ռ�������ɲ����ˡ�

335         if (!sh_bang) {

336                 p = copy_strings(envc,envp,page,p,0);

337                 p = copy_strings(argc,argv,page,p,0);

338                 if (!p) {

339                         retval = -ENOMEM;

340                         goto exec_error2;

341                 }

342         }

343 /* OK, This is the point of no return */

344 /* note that current->library stays unchanged by an exec */

    /* OK�����濪ʼ��û�з��صĵط��� */

    // ǰ��������Ժ��������ṩ����Ϣ����Ҫ����ִ���ļ��������в����ͻ����ռ���������ã�

    // ����û��Ϊִ���ļ�����ʲôʵ���ԵĹ���������û������Ϊִ���ļ���ʼ����������ṹ

    // ��Ϣ������ҳ���ȹ������������Ǿ�������Щ����������ִ���ļ�ֱ��ʹ�õ�ǰ���̵ġ���

    // �ǡ�������ǰ���̽��������ִ���ļ��Ľ��̣����������Ҫ�����ͷŵ�ǰ����ռ�õ�ijЩ

    // ϵͳ��Դ�������ر�ָ�����Ѵ��ļ���ռ�õ�ҳ�����ڴ�ҳ��ȡ�Ȼ�����ִ���ļ�ͷ��

    // ����Ϣ�޸ĵ�ǰ����ʹ�õľֲ���������LDT�������������ݣ��������ô���κ����ݶ���

    // �������޳���������ǰ�洦���õ���e_uid��e_gid����Ϣ�����ý�������ṹ����ص���

    // �Ρ�����ִ�б���ϵͳ���ó���ķ��ص�ַ eip[]ָ��ִ���ļ��д������ʼλ�ô�����

    // ������ϵͳ�����˳����غ�ͻ�ȥ������ִ���ļ��Ĵ����ˡ�ע�⣬��Ȼ��ʱ��ִ���ļ���

    // ������ݻ�û�д��ļ��м��ص��ڴ��У���������ͻ������Ѿ���copy_strings() ��ʹ��

    // get_free_page()�����������ڴ�ҳ���������ݣ�����change_ldt()������ʹ��put_page()

    // ���˽����߼��ռ��ĩ�˴������⣬��create_tables()��Ҳ���������û�ջ�ϴ�Ų���

    // �ͻ���ָ���������ȱҳ�쳣���Ӷ��ڴ��������Ҳ��ʹ�Ϊ�û�ջ�ռ�ӳ�������ڴ�ҳ��

    //

    // �����������ȷŻؽ���ԭִ�г����i�ڵ㣬�����ý���executable �ֶ�ָ����ִ���ļ�

    // ��i�ڵ㡣Ȼ��λԭ���̵������źŴ��������������SIG_IGN������븴λ���ٸ�����

    // ����ִ��ʱ�ر��ļ������close_on_exec��λͼ��־���ر�ָ���Ĵ��ļ�����λ�ñ�־��

345         if (current->executable)

346                 iput(current->executable);

347         current->executable = inode;

348         current->signal = 0;

349         for (i=0 ; i<32 ; i++) {

350                 current->sigaction[i].sa_mask = 0;

351                 current->sigaction[i].sa_flags = 0;

352                 if (current->sigaction[i].sa_handler != SIG_IGN)

353                         current->sigaction[i].sa_handler = NULL;

354         }

355         for (i=0 ; i<NR_OPEN ; i++)

356                 if ((current->close_on_exec>>i)&1)

357                         sys_close(i);

358         current->close_on_exec = 0;

    // Ȼ����ݵ�ǰ����ָ���Ļ���ַ���޳����ͷ�ԭ������Ĵ���κ����ݶ�����Ӧ���ڴ�ҳ��

    // ָ���������ڴ�ҳ�漰ҳ����������ʱ��ִ���ļ���û��ռ�����ڴ����κ�ҳ�棬����ڴ�

    // ��������������ִ���ļ�����ʱ�ͻ�����ȱҳ�쳣�жϣ���ʱ�ڴ�������򼴻�ִ��ȱҳ��

    // ����Ϊ��ִ���ļ������ڴ�ҳ����������ҳ������Ұ����ִ���ļ�ҳ������ڴ��С�

    // ������ϴ�����ʹ����Э��������ָ����ǵ�ǰ���̣������ÿգ�����λʹ����Э������

    // �ı�־��

359         free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));

360         free_page_tables(get_base(current->ldt[2]),get_limit(0x17));

361         if (last_task_used_math == current)

362                 last_task_used_math = NULL;

363         current->used_math = 0;

    // Ȼ�����Ǹ�����ִ���ļ�ͷ�ṹ�еĴ��볤���ֶ� a_text ��ֵ�޸ľֲ�������������ַ��

    // ���޳�������128KB �IJ����ͻ����ռ�ҳ����������ݶ�ĩ�ˡ�ִ���������֮��p��ʱ

    // ���ij������ݶ���ʼ��Ϊԭ���ƫ��ֵ������ָ������ͻ����ռ����ݿ�ʼ��������ת����

    // Ϊջָ��ֵ��Ȼ������ڲ�����create_tables() ��ջ�ռ��д��������Ͳ�������ָ�����

    // �������main()��Ϊ����ʹ�ã������ظ�ջָ�롣

364         p += change_ldt(ex.a_text,page);

365         p -= LIBRARY_SIZE + MAX_ARG_PAGES*PAGE_SIZE;

366         p = (unsigned long) create_tables((char *)p,argc,envc);

 

    // �������޸Ľ��̸��ֶ�ֵΪ��ִ���ļ�����Ϣ�������������ṹ����β�ֶ�end_code��

    // ��ִ���ļ��Ĵ���γ��� a_text������β�ֶ� end_data ����ִ���ļ��Ĵ���γ��ȼ���

    // �ݶγ��ȣ�a_data + a_text����������̶ѽ�β�ֶ�brk = a_text + a_data + a_bss��

    // brk����ָ�����̵�ǰ���ݶΣ�����δ��ʼ�����ݲ��֣�ĩ��λ�ã����ں�Ϊ���̷����ڴ�

    // ʱָ�����俪ʼλ�á�Ȼ�����ý���ջ��ʼ�ֶ�Ϊջָ������ҳ�棬���������ý��̵���Ч

    // �û�id����Ч��id��

367         current->brk = ex.a_bss +

368                 (current->end_data = ex.a_data +

369                 (current->end_code = ex.a_text));

370         current->start_stack = p & 0xfffff000;

371         current->suid = current->euid = e_uid;

372         current->sgid = current->egid = e_gid;

    // ���ԭ����ϵͳ�жϵij����ڶ�ջ�ϵĴ���ָ���滻Ϊָ����ִ�г������ڵ㣬����ջ

    // ָ���滻Ϊ��ִ���ļ���ջָ�롣�˺󷵻�ָ�������Щջ���ݲ�ʹ��CPUȥִ����ִ��

    // �ļ�����˲��᷵�ص�ԭ����ϵͳ�жϵij�����ȥ�ˡ�

373         eip[0] = ex.a_entry;    /* eip, magic happens :-) */  /* eip��ħ����������*/

374         eip[3] = p;             /* stack pointer */           /* esp����ջָ�� */

375         return 0;

376 exec_error2:

377         iput(inode);                       // �Ż�i�ڵ㡣

378 exec_error1:

379         for (i=0 ; i<MAX_ARG_PAGES ; i++)

380                 free_page(page[i]);        // �ͷŴ�Ų����ͻ��������ڴ�ҳ�档

381         return(retval);                    // ���س����롣

382 }

383