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