1 /*
2 * linux/kernel/exit.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #define DEBUG_PROC_TREE // ������š����Խ���������
8
9 #include <errno.h> // �����ͷ�ļ�������ϵͳ�и��ֳ����š�(Linus��minix��������)
10 #include <signal.h> // �ź�ͷ�ļ��������źŷ��ų������źŽṹ�Լ��źŲ�������ԭ�͡�
11 #include <sys/wait.h> // �ȴ�����ͷ�ļ�������ϵͳ����wait()��waitpid()����س������š�
12
13 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0���ݵȡ�
14 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
15 #include <linux/tty.h> // ttyͷ�ļ����������й�tty_io������ͨ�ŷ���IJ�����������
16 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
17
18 int sys_pause(void); // �ѽ�����Ϊ˯��״̬��ֱ���յ��źţ�kernel/sched.c��164�У���
19 int sys_close(int fd); // �ر�ָ���ļ���ϵͳ���ã�fs/open.c��219�У���
20
//// �ͷ�ָ������ռ�õ�����ۼ����������ݽṹռ�õ��ڴ�ҳ�档
// ����p ���������ݽṹָ�롣�ú����ں���� sys_kill() �� sys_waitpid() �����б����á�
// ɨ������ָ������� task[] ��Ѱ��ָ������������ҵ�����������ո�����ۣ�Ȼ���ͷ�
// ���������ݽṹ��ռ�õ��ڴ�ҳ�棬���ִ�е��Ⱥ������ڷ���ʱ�����˳����������������
// ����û���ҵ�ָ�������Ӧ������ں�panicJ��
21 void release(struct task_struct * p)
22 {
23 int i;
24
// �������������ṹָ��ΪNULL���˳��������ָ��ָ��ǰ��������ʾ������Ϣ�˳���
25 if (!p)
26 return;
27 if (p == current) {
28 printk("task releasing itself\n\r");
29 return;
30 }
// ɨ������ṹָ�����飬Ѱ��ָ��������p������ҵ������ÿ�����ָ�������ж�Ӧ�����
// ��������ṹ֮��Ĺ���ָ�룬�ͷ�����p���ݽṹռ�õ��ڴ�ҳ�档�����ִ�е��ȳ���
// ���غ��˳������û���ҵ�ָ��������p����˵���ں˴�������ˣ�����ʾ������Ϣ��������
// �������Ӳ��ֵĴ�����ָ������p��˫��������ɾ����
31 for (i=1 ; i<NR_TASKS ; i++)
32 if (task[i]==p) {
33 task[i]=NULL;
34 /* Update links */ /* �������� */
// ���p����������ϣ����ӽ��̣����ñ����ϵı��ڽ���ָ������µı��ڽ��̡����p
// �������µ��ӽ��̣����ñ����µı����ӽ���ָ����ڵ��Ͻ��̡� �������p �������µ�
// �ӽ��̣�����Ҫ�����丸���̵������ӽ���ָ��cptrΪָ��p�ı����ӽ��̡�
// ָ��osptr��old sibling pointer��ָ���p�ȴ������ֵܽ��̡�
// ָ��ysptr��younger sibling pointer��ָ���p�����ֵܽ��̡�
// ָ��pptr��parent pointer��ָ��p�ĸ����̡�
// ָ��cptr��child pointer���Ǹ�����ָ�����£���������ӽ��̡�
35 if (p->p_osptr)
36 p->p_osptr->p_ysptr = p->p_ysptr;
37 if (p->p_ysptr)
38 p->p_ysptr->p_osptr = p->p_osptr;
39 else
40 p->p_pptr->p_cptr = p->p_osptr;
41 free_page((long)p);
42 schedule();
43 return;
44 }
45 panic("trying to release non-existent task");
46 }
47
48 #ifdef DEBUG_PROC_TREE
// ��������˷���DEBUG_PROC_TREE�������ʱ�������´��롣
49 /*
50 * Check to see if a task_struct pointer is present in the task[] array
51 * Return 0 if found, and 1 if not found.
52 */
/*
* ���task[]�������Ƿ����һ��ָ����task_struct�ṹָ��p��
* ���������0������1��
*/
// �������ṹָ��p��
53 int bad_task_ptr(struct task_struct *p)
54 {
55 int i;
56
57 if (!p)
58 return 0;
59 for (i=0 ; i<NR_TASKS ; i++)
60 if (task[i] == p)
61 return 0;
62 return 1;
63 }
64
65 /*
66 * This routine scans the pid tree and make sure the rep invarient still
67 * holds. Used for debugging only, since it's very slow....
68 *
69 * It looks a lot scarier than it really is.... we're doing nothing more
70 * than verifying the doubly-linked list found in p_ysptr and p_osptr,
71 * and checking it corresponds with the process tree defined by p_cptr and
72 * p_pptr;
73 */
/*
* ����ĺ�������ɨ�����������ȷ�����Ĺ���������Ȼ��ȷ�������ڵ�ʽ��
* ��Ϊ�ú����Ƚ���....
*
* �ú�������ȥҪ��ʵ�ʵĿֲ�.... ��ʵ���ǽ�����֤��ָ��p_ysptr��
* p_osptr���ɵ�˫���������������������ָ��p_cptr��p_pptr���ɵ�
* ������֮��Ĺ�ϵ��
*/
// ����������
74 void audit_ptree()
75 {
76 int i;
77
// ɨ��ϵͳ�еij�����0��������������������4��ָ�루pptr��cptr��ysptr��osptr��
// ����ȷ�ԡ�����������ۣ��Ϊ����������
78 for (i=1 ; i<NR_TASKS ; i++) {
79 if (!task[i])
80 continue;
// �������ĸ�����ָ��p_pptrû��ָ���κν��̣��������������в����ڣ�������ʾ������Ϣ
// �����棬pid��N�ĸ��������������⡱����������cptr��ysptr��osptr�������Ʋ�����
81 if (bad_task_ptr(task[i]->p_pptr))
82 printk("Warning, pid %d's parent link is bad\n",
83 task[i]->pid);
84 if (bad_task_ptr(task[i]->p_cptr))
85 printk("Warning, pid %d's child link is bad\n",
86 task[i]->pid);
87 if (bad_task_ptr(task[i]->p_ysptr))
88 printk("Warning, pid %d's ys link is bad\n",
89 task[i]->pid);
90 if (bad_task_ptr(task[i]->p_osptr))
91 printk("Warning, pid %d's os link is bad\n",
92 task[i]->pid);
// �������ĸ�����ָ��p_pptrָ�����Լ�������ʾ������Ϣ�����棬pid��N�ĸ���������
// ָ��ָ�����Լ�������������cptr��ysptr��osptr�������Ʋ�����
93 if (task[i]->p_pptr == task[i])
94 printk("Warning, pid %d parent link points to self\n");
95 if (task[i]->p_cptr == task[i])
96 printk("Warning, pid %d child link points to self\n");
97 if (task[i]->p_ysptr == task[i])
98 printk("Warning, pid %d ys link points to self\n");
99 if (task[i]->p_osptr == task[i])
100 printk("Warning, pid %d os link points to self\n");
// ��������б��Լ��ȴ����ı����ֵܽ��̣���ô�ͼ�������Ƿ��й�ͬ�ĸ����̣���������
// ���ֽ��̵�ysptrָ���Ƿ���ȷ��ָ���̡�������ʾ������Ϣ��
101 if (task[i]->p_osptr) {
102 if (task[i]->p_pptr != task[i]->p_osptr->p_pptr)
103 printk(
104 "Warning, pid %d older sibling %d parent is %d\n",
105 task[i]->pid, task[i]->p_osptr->pid,
106 task[i]->p_osptr->p_pptr->pid);
107 if (task[i]->p_osptr->p_ysptr != task[i])
108 printk(
109 "Warning, pid %d older sibling %d has mismatched ys link\n",
110 task[i]->pid, task[i]->p_osptr->pid);
111 }
// ��������б��Լ����ı����ֵܽ��̣���ô�ͼ�������Ƿ��й�ͬ�ĸ����̣���������
// С�ܽ��̵�osptrָ���Ƿ���ȷ��ָ���̡�������ʾ������Ϣ��
112 if (task[i]->p_ysptr) {
113 if (task[i]->p_pptr != task[i]->p_ysptr->p_pptr)
114 printk(
115 "Warning, pid %d younger sibling %d parent is %d\n",
116 task[i]->pid, task[i]->p_osptr->pid,
117 task[i]->p_osptr->p_pptr->pid);
118 if (task[i]->p_ysptr->p_osptr != task[i])
119 printk(
120 "Warning, pid %d younger sibling %d has mismatched os link\n",
121 task[i]->pid, task[i]->p_ysptr->pid);
122 }
// �������������ӽ���ָ��cptr���գ���ô�����ӽ��̵ĸ������Ƿ��DZ����̣�������
// �ӽ��̵�С�ܽ���ָ��yspter�Ƿ�Ϊ�ա�����������ʾ������Ϣ��
123 if (task[i]->p_cptr) {
124 if (task[i]->p_cptr->p_pptr != task[i])
125 printk(
126 "Warning, pid %d youngest child %d has mismatched parent link\n",
127 task[i]->pid, task[i]->p_cptr->pid);
128 if (task[i]->p_cptr->p_ysptr)
129 printk(
130 "Warning, pid %d youngest child %d has non-NULL ys link\n",
131 task[i]->pid, task[i]->p_cptr->pid);
132 }
133 }
134 }
135 #endif /* DEBUG_PROC_TREE */
136
//// ��ָ������p�����ź�sig��Ȩ��Ϊpriv��
// ������sig - �ź�ֵ��p - ָ�������ָ�룻priv - ǿ�Ʒ����źŵı�־��������Ҫ���ǽ���
// �û����Ի���ܷ����źŵ�Ȩ�����ú��������жϲ�������ȷ�ԣ�Ȼ���ж������Ƿ����㡣
// ����������ָ�����̷����ź�sig���˳�������δ���ɴ���š�
137 static inline int send_sig(long sig,struct task_struct * p,int priv)
138 {
// ���û��Ȩ�ޣ����ҵ�ǰ���̵���Ч�û�ID�����p�IJ�ͬ������Ҳ���dz����û�����˵��
// û����p�����źŵ�Ȩ����suser()����Ϊ(current->euid==0)�������ж��Ƿ��dz����û���
139 if (!p)
140 return -EINVAL;
141 if (!priv && (current->euid!=p->euid) && !suser())
142 return -EPERM;
// ����Ҫ���͵��ź���SIGKILL�� SIGCONT����ô�����ʱ�����źŵĽ��� p������ֹͣ״̬
// ������Ϊ���������У�״̬��Ȼ���Ľ���p���ź�λͼsignal��ȥ������λ���ᵼ�½���
// ֹͣ���ź�SIGSTOP��SIGTSTP��SIGTTIN��SIGTTOU��
143 if ((sig == SIGKILL) || (sig == SIGCONT)) {
144 if (p->state == TASK_STOPPED)
145 p->state = TASK_RUNNING;
146 p->exit_code = 0;
147 p->signal &= ~( (1<<(SIGSTOP-1)) | (1<<(SIGTSTP-1)) |
148 (1<<(SIGTTIN-1)) | (1<<(SIGTTOU-1)) );
149 }
150 /* If the signal will be ignored, don't even post it */
/* ���Ҫ���͵��ź�sig��������p���Ե�����ô�������÷��� */
151 if ((int) p->sigaction[sig-1].sa_handler == 1)
152 return 0;
153 /* Depends on order SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU */
/* �����ж�������SIGSTOP��SIGTSTP��SIGTTIN��SIGTTOU�Ĵ��� */
// ����ź���SIGSTOP��SIGTSTP��SIGTTIN��SIGTTOU֮һ����ô˵��Ҫ�ý����źŵĽ���p
// ֹͣ���С���ˣ���p ���ź�λͼ���� SIGCONT ��λ������Ҫ��λλͼ�м������е��ź�
// SIGCONT�����
154 if ((sig >= SIGSTOP) && (sig <= SIGTTOU))
155 p->signal &= ~(1<<(SIGCONT-1));
156 /* Actually deliver the signal */
/* ������������p�����ź�p */
157 p->signal |= (1<<(sig-1));
158 return 0;
159 }
160
// ���ݽ������pgrpȡ�ý����������ĻỰ�š�
// ɨ���������飬Ѱ�ҽ������Ϊpgrp�Ľ��̣���������Ự�š����û���ҵ�ָ���������
// Ϊpgrp���κν��̣���-1��
161 int session_of_pgrp(int pgrp)
162 {
163 struct task_struct **p;
164
165 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
166 if ((*p)->pgrp == pgrp)
167 return((*p)->session);
168 return -1;
169 }
170
// ��ֹ�����飨������鷢���źţ���
// ������pgrp - ָ���Ľ�����ţ�sig - ָ�����źţ�priv - Ȩ�ޡ�
// ����ָ��������pgrp�е�ÿ�����̷���ָ���ź�sig��ֻҪ��һ�����̷��ͳɹ����ͻ�
// ����0���������û���ҵ�ָ���������pgrp���κ�һ�����̣��س�����-ESRCH����
// �ҵ����������pgrp�Ľ��̣����Ƿ����ź�ʧ�ܣ��ط���ʧ�ܵĴ����롣
171 int kill_pg(int pgrp, int sig, int priv)
172 {
173 struct task_struct **p;
174 int err,retval = -ESRCH; // -ESRCH��ʾָ���Ľ��̲����ڡ�
175 int found = 0;
176
// �����жϸ������źźͽ�������Ƿ���Ч��Ȼ��ɨ��ϵͳ������������ɨ�赽�������Ϊ
// pgrp�Ľ��̣������䷢���ź�sig��ֻҪ��һ���źŷ��ͳɹ����������ͻ᷵��0��
177 if (sig<1 || sig>32 || pgrp<=0)
178 return -EINVAL;
179 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
180 if ((*p)->pgrp == pgrp) {
181 if (sig && (err = send_sig(sig,*p,priv)))
182 retval = err;
183 else
184 found++;
185 }
186 return(found ? 0 : retval);
187 }
188
// ��ֹ���̣�����̷����źţ���
// ������pid - ���̺ţ�sig - ָ���źţ�priv - Ȩ�ޡ�
// ������̺�Ϊpid�Ľ��̷���ָ���ź�sig�����ҵ�ָ��pid�Ľ��̣���ô���źŷ��ͳɹ���
// ��0�������źŷ��ͳ����š����û���ҵ�ָ�����̺�pid�Ľ��̣��س�����
// -ESRCH��ָ�����̲����ڣ���
189 int kill_proc(int pid, int sig, int priv)
190 {
191 struct task_struct **p;
192
193 if (sig<1 || sig>32)
194 return -EINVAL;
195 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
196 if ((*p)->pid == pid)
197 return(sig ? send_sig(sig,*p,priv) : 0);
198 return(-ESRCH);
199 }
200
201 /*
202 * POSIX specifies that kill(-1,sig) is unspecified, but what we have
203 * is probably wrong. Should make it like BSD or SYSV.
204 */
/*
* POSIX��ָ��kill(-1,sig)δ���塣��������֪���Ŀ��ܴ��ˡ�Ӧ������
* ��BSD��SYSVϵͳһ����
*/
//// ϵͳ����kill()���������κν��̻�����鷢���κ��źţ�������ֻ��ɱ������J��
// ����pid�ǽ��̺ţ�sig����Ҫ���͵��źš�
// ���pidֵ>0�����źű��������̺���pid�Ľ��̡�
// ���pid=0����ô�źžͻᱻ������ǰ���̵Ľ����������еĽ��̡�
// ���pid=-1�����ź�sig�ͻᷢ������һ�����̣���ʼ���̣�������н��̡�
// ���pid < -1�����ź�sig������������-pid�����н��̡�
// ����ź�sigΪ0�������źţ����Ի���д����顣����ɹ���0��
// �ú���ɨ�������������������pid�����������Ľ��̷���ָ���ź�sig����pid����0��
// ������ǰ�����ǽ������鳤�������Ҫ���������ڵĽ���ǿ�Ʒ����ź�sig��
205 int sys_kill(int pid,int sig)
206 {
207 struct task_struct **p = NR_TASKS + task; // pָ�������������һ�
208 int err, retval = 0;
209
210 if (!pid)
211 return(kill_pg(current->pid,sig,0));
212 if (pid == -1) {
213 while (--p > &FIRST_TASK)
214 if (err = send_sig(sig,*p,0))
215 retval = err;
216 return(retval);
217 }
218 if (pid < 0)
219 return(kill_pg(-pid,sig,0));
220 /* Normal kill */
221 return(kill_proc(pid,sig,0));
222 }
223
224 /*
225 * Determine if a process group is "orphaned", according to the POSIX
226 * definition in 2.2.2.52. Orphaned process groups are not to be affected
227 * by terminal-generated stop signals. Newly orphaned process groups are
228 * to receive a SIGHUP and a SIGCONT.
229 *
230 * "I ask you, have you ever known what it is to be an orphan?"
231 */
/*
* ����POSIX��2.2.2.52���еĶ��壬ȷ��һ���������Ƿ��ǡ��¶������¶�����
* �鲻���ܵ��ն˲�����ֹͣ�źŵ�Ӱ�졣�½������Ŷ������齫���յ�һ��SIGHUP
* �źź�һ��SIGCONT�źš�
*
* �������㣬���Ƿ�����֪����Ϊһ���¶���ζ��ʲô����
*/
// �����ᵽ��POSIX P1003.1 2.2.2.52���ǹ��ڹ¶������������������������µ�һ������
// ��ֹʱ���ܵ��½������ɡ��¶����� һ�������鵽������ĸ�����֮�����ϵ�����ڸø�
// ���̺����ӽ������ߡ���ˣ����������һ�����Ӹ����̵Ľ��̻����һ�������̵�ֱ�Ӻ���
// ��ֹ�Ļ�����ô���������ͻ��Ϊһ���¶������顣���κ�һ������£�������̵���ֹ��
// �½������ɹ¶������飬��ô�������е����н��̾ͻ������ǵ���ҵ����shell�Ͽ���ϵ��
// ��ҵ����shell�����پ��иý�������ڵ��κ���Ϣ�����ý������д���ֹͣ״̬�Ľ��̽���
// ��Զ��ʧ��Ϊ�˽��������⣬����ֹͣ״̬���̵��½������Ŷ����������Ҫ���յ�һ��
// SIGHUP�źź�һ��SIGCONT�źţ�����ָʾ�����Ѿ������ǵĻỰ�� session���жϿ���ϵ��
// SIGHUP�źŽ����½������г�Ա����ֹ���������Dz���������SIGHUP�źš��� SIGCONT��
// �Ž�ʹ��Щû�б�SIGHUP�ź���ֹ�Ľ��̼������С� ���ڴ��������£����������һ����
// �̴���ֹͣ״̬����ô�������еĽ��̿��ܶ�����ֹͣ״̬��
//
// �ж�һ���������Ƿ��ǹ¶����̡����������0���������1��
// ɨ���������顣���������գ����߽��̵������ָ���IJ�ͬ�����߽����Ѿ����ڽ���״̬��
// ���߽��̵ĸ�������init���̣���˵��ɨ��Ľ��̲���ָ��������ij�Ա�����߲�����Ҫ��
// ���������� ����˵���ý�����ָ����ij�Ա�����丸���̲��� init���̡���ʱ����ý���
// �����̵���Ų�����ָ�������pgrp���������̵ĻỰ�ŵ��ڽ��̵ĻỰ�ţ���˵������ͬ
// ����һ���Ự�����ָ����pgrp������϶����ǹ¶������顣����...��
232 int is_orphaned_pgrp(int pgrp)
233 {
234 struct task_struct **p;
235
236 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
237 if (!(*p) ||
238 ((*p)->pgrp != pgrp) ||
239 ((*p)->state == TASK_ZOMBIE) ||
240 ((*p)->p_pptr->pid == 1))
241 continue;
242 if (((*p)->p_pptr->pgrp != pgrp) &&
243 ((*p)->p_pptr->session == (*p)->session))
244 return 0;
245 }
246 return(1); /* (sighing) "Often!" */ /* �������ǹ¶������飡*/
247 }
248
// �жϽ��������Ƿ��д���ֹͣ״̬����ҵ�������飩������1������0��
// ���ҷ�����ɨ�������������顣�������ָ����pgrp���κν����Ƿ���ֹͣ״̬��
249 static int has_stopped_jobs(int pgrp)
250 {
251 struct task_struct ** p;
252
253 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
254 if ((*p)->pgrp != pgrp)
255 continue;
256 if ((*p)->state == TASK_STOPPED)
257 return(1);
258 }
259 return(0);
260 }
261
// �����˳�����������������365�д���ϵͳ���ô�������sys_exit()���á�
// �ú��������ݵ�ǰ�������������Զ�����д��������ѵ�ǰ����״̬���óɽ���״̬
// TASK_ZOMBIE�������õ��Ⱥ���schedule()ȥִ���������̣����ٷ��ء�
262 volatile void do_exit(long code)
263 {
264 struct task_struct *p;
265 int i;
266
// �����ͷŵ�ǰ���̴���κ����ݶ���ռ���ڴ�ҳ�� ����free_page_tables() �ĵ�1������
// ��get_base()����ֵ��ָ����CPU���Ե�ַ�ռ�����ʼ����ַ����2����get_limit()����ֵ��
// ˵�����ͷŵ��ֽڳ���ֵ��get_base()���е�current->ldt[1]�������̴������������λ��
// ��current->ldt[2]�������̴������������λ�ã���get_limit()�е�0x0f�ǽ��̴���ε�
// ѡ�����0x17�ǽ������ݶε�ѡ�����������ȡ�λ���ַʱʹ�øöε�������������ַ��Ϊ
// ������ȡ�γ���ʱʹ�øöε�ѡ�����Ϊ������ free_page_tables()����λ��mm/memory.c
// �ļ��ĵ�69�п�ʼ����get_base()��get_limit()��λ��include/linux/sched.hͷ�ļ��ĵ�
// 264�п�ʼ����
267 free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
268 free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
// Ȼ��رյ�ǰ���̴��ŵ������ļ����ٶԵ�ǰ���̵Ĺ���Ŀ¼pwd����Ŀ¼root��ִ�г���
// �ļ��� i�ڵ��Լ����ļ�����ͬ���������Żظ��� i�ڵ㲢�ֱ��ÿգ��ͷţ��� ���Űѵ�ǰ
// ���̵�״̬����Ϊ����״̬��TASK_ZOMBIE���������ý����˳��롣
269 for (i=0 ; i<NR_OPEN ; i++)
270 if (current->filp[i])
271 sys_close(i);
272 iput(current->pwd);
273 current->pwd = NULL;
274 iput(current->root);
275 current->root = NULL;
276 iput(current->executable);
277 current->executable = NULL;
278 iput(current->library);
279 current->library = NULL;
280 current->state = TASK_ZOMBIE;
281 current->exit_code = code;
282 /*
283 * Check to see if any process groups have become orphaned
284 * as a result of our exiting, and if they have any stopped
285 * jobs, send them a SIGUP and then a SIGCONT. (POSIX 3.2.2.2)
286 *
287 * Case i: Our father is in a different pgrp than we are
288 * and we were the only connection outside, so our pgrp
289 * is about to become orphaned.
290 */
/*
* ��鵱ǰ���̵��˳��Ƿ������κν������ɹ¶������顣���
* �У������д���ֹͣ״̬��TASK_STOPPED������Ա���������Ƿ���
* һ��SIGHUP�źź�һ��SIGCONT�źš���POSIX 3.2.2.2��Ҫ��
*
* ���1�����ǵĸ�����������һ�������Dz�ͬ�Ľ������У���������
* ������������Ψһ��ϵ���������ǵĽ����齫���һ���¶������顣
*/
// POSIX 3.2.2.2��1991�棩�ǹ���exit()������˵����������������ڵĽ������뵱ǰ���̵�
// ��ͬ����������ͬһ���Ự��session���У����ҵ�ǰ�������ڽ����齫Ҫ��ɹ¶������˲���
// ��ǰ���̵Ľ������к��д���ֹͣ״̬����ҵ�����̣�����ô��Ҫ�������ǰ���̵Ľ����鷢
// �������źţ�SIGHUP��SIGCONT�������������źŵ�ԭ���232��ǰ��˵����
291 if ((current->p_pptr->pgrp != current->pgrp) &&
292 (current->p_pptr->session == current->session) &&
293 is_orphaned_pgrp(current->pgrp) &&
294 has_stopped_jobs(current->pgrp)) {
295 kill_pg(current->pgrp,SIGHUP,1);
296 kill_pg(current->pgrp,SIGCONT,1);
297 }
298 /* Let father know we died */ /* ֪ͨ�����̵�ǰ���̽���ֹ */
299 current->p_pptr->signal |= (1<<(SIGCHLD-1));
300
301 /*
302 * This loop does two things:
303 *
304 * A. Make init inherit all the child processes
305 * B. Check to see if any process groups have become orphaned
306 * as a result of our exiting, and if they have any stopped
307 * jons, send them a SIGUP and then a SIGCONT. (POSIX 3.2.2.2)
308 */
/*
* �����ѭ�������������飺
*
* A. ��init���̼̳е�ǰ���������ӽ��̡�
* B. ��鵱ǰ���̵��˳��Ƿ������κν������ɹ¶������顣���
* �У������д���ֹͣ״̬��TASK_STOPPED������Ա���������Ƿ���
* һ��SIGHUP�źź�һ��SIGCONT�źš���POSIX 3.2.2.2��Ҫ��
*/
// �����ǰ�������ӽ��̣���p_cptrָ��ָ������������ӽ��̣������ý���1��init���̣�
// ��Ϊ�������ӽ��̵ĸ����̡�����ӽ����Ѿ����ڽ���״̬������init���̣������̣�����
// �ӽ�������ֹ�ź�SIGCHLD��
309 if (p = current->p_cptr) {
310 while (1) {
311 p->p_pptr = task[1];
312 if (p->state == TASK_ZOMBIE)
313 task[1]->signal |= (1<<(SIGCHLD-1));
314 /*
315 * process group orphan check
316 * Case ii: Our child is in a different pgrp
317 * than we are, and it was the only connection
318 * outside, so the child pgrp is now orphaned.
319 */
/* �¶��������⡣
* ���2�����ǵ��ӽ����ڲ�ͬ�Ľ������У���������
* ������Ψһ���������ӡ���������ӽ������ڽ���
* �齫��ɹ¶��������ˡ�
*/
// ����ӽ����뵱ǰ���̲���ͬһ���������е�����ͬһ��session�У����ҵ�ǰ�������ڽ���
// �齫Ҫ��ɹ¶������ˣ����ҵ�ǰ���̵Ľ������к��д���ֹͣ״̬����ҵ�����̣�����ô��
// Ҫ�������ǰ���̵Ľ����鷢�������źţ�SIGHUP��SIGCONT�� ������ӽ������ֵܽ��̣�
// �����ѭ��������Щ�ֵܽ��̡�
320 if ((p->pgrp != current->pgrp) &&
321 (p->session == current->session) &&
322 is_orphaned_pgrp(p->pgrp) &&
323 has_stopped_jobs(p->pgrp)) {
324 kill_pg(p->pgrp,SIGHUP,1);
325 kill_pg(p->pgrp,SIGCONT,1);
326 }
327 if (p->p_osptr) {
328 p = p->p_osptr;
329 continue;
330 }
331 /*
332 * This is it; link everything into init's children
333 * and leave
334 */
/*
* ���������������ӽ������ӳ�Ϊinit���ӽ��̲��˳�ѭ����
*/
// ͨ�����洦������ǰ�����ӽ��̵������ֵ��ӽ��̶��Ѿ�����������ʱpָ�����ϵ��ֵ���
// ���̡����ǰ���Щ�ֵ��ӽ���ȫ������init���̵��ӽ���˫������ͷ���С������init
// ���̵�p_cptr ָ��ǰ����ԭ�ӽ�����������ģ�the youngest���ӽ��̣���ԭ�ӽ�����
// ���ϵģ�the oldest���ֵ��ӽ��� p_osptr ָ��ԭ init���̵���������̣���ԭinit��
// ������������̵� p_ysptrָ��ԭ�ӽ��������ϵ��ֵ��ӽ��̡����ѵ�ǰ���̵�p_cptr
// ָ���ÿգ����˳�ѭ����
335 p->p_osptr = task[1]->p_cptr;
336 task[1]->p_cptr->p_ysptr = p;
337 task[1]->p_cptr = current->p_cptr;
338 current->p_cptr = 0;
339 break;
340 }
341 }
// �����ǰ�����ǻỰͷ��(leader)���̣���ô�����п����նˣ���������ʹ�øÿ����ն˵�
// �����鷢�Ҷ��ź�SIGHUP��Ȼ���ͷŸ��նˡ�����ɨ���������飬�����ڵ�ǰ���̻Ự��
// ���̵��ն��ÿգ�ȡ������
342 if (current->leader) {
343 struct task_struct **p;
344 struct tty_struct *tty;
345
346 if (current->tty >= 0) {
347 tty = TTY_TABLE(current->tty);
348 if (tty->pgrp>0)
349 kill_pg(tty->pgrp, SIGHUP, 1);
350 tty->pgrp = 0;
351 tty->session = 0;
352 }
353 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
354 if ((*p)->session == current->session)
355 (*p)->tty = -1;
356 }
// �����ǰ�����ϴ�ʹ�ù�Э����������Ѽ�¼����Ϣ��ָ���ÿա��������˵��Խ��������ţ�
// ����ý����������ʾ�����������õ��Ⱥ��������µ��Ƚ������У����ø������ܹ�����
// �������̵������ƺ����ˡ�
357 if (last_task_used_math == current)
358 last_task_used_math = NULL;
359 #ifdef DEBUG_PROC_TREE
360 audit_ptree();
361 #endif
362 schedule();
363 }
364
// ϵͳ����exit()����ֹ���̡�
// ����error_code���û������ṩ���˳�״̬��Ϣ��ֻ�е��ֽ���Ч����error_code����8
// ������ wait() �� waitpid()������Ҫ���ֽ��н���������wait()��״̬��Ϣ�����磬
// ������̴�����ͣ״̬��TASK_STOPPED������ô����ֽھ͵��� 0x7f���μ� sys/wait.h
// �ļ���13--19�С� wait() ��waitpid() ������Щ��Ϳ���ȡ���ӽ��̵��˳�״̬�����
// ������ֹ��ԭ���źţ���
365 int sys_exit(int error_code)
366 {
367 do_exit((error_code&0xff)<<8);
368 }
369
// ϵͳ����waitpid()������ǰ���̣�ֱ��pid ָ�����ӽ����˳�����ֹ�������յ�Ҫ����ֹ
// �ý��̵��źţ���������Ҫ����һ���źž�����źŴ����������pid��ָ���ӽ�������
// �˳����ѳ���ν�Ľ������̣������ý����̷��ء��ӽ���ʹ�õ�������Դ���ͷš�
// ���pid > 0����ʾ�ȴ����̺ŵ���pid���ӽ��̡�
// ���pid = 0����ʾ�ȴ�������ŵ��ڵ�ǰ������ŵ��κ��ӽ��̡�
// ���pid < -1����ʾ�ȴ�������ŵ���pid����ֵ���κ��ӽ��̡�
// ���pid = -1����ʾ�ȴ��κ��ӽ��̡�
// ��options = WUNTRACED����ʾ����ӽ�����ֹͣ�ģ�Ҳ���Ϸ��أ�������٣���
// ��options = WNOHANG����ʾ���û���ӽ����˳�����ֹ�����Ϸ��ء�
// �������״ָ̬��stat_addr��Ϊ�գ���ͽ�״̬��Ϣ���浽���
// ����pid�ǽ��̺ţ�*stat_addr�DZ���״̬��Ϣλ�õ�ָ�룻options��waitpidѡ�
370 int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
371 {
372 int flag; // �ñ�־���ں����ʾ��ѡ�����ӽ��̴��ھ�����˯��̬��
373 struct task_struct *p;
374 unsigned long oldblocked;
375
// ������֤��Ҫ���״̬��Ϣ��λ�ô��ڴ�ռ��㹻��Ȼ��λ��־flag�����Ŵӵ�ǰ���̵���
// �����ӽ��̿�ʼɨ���ӽ����ֵ�������
376 verify_area(stat_addr,4);
377 repeat:
378 flag=0;
379 for (p = current->p_cptr ; p ; p = p->p_osptr) {
// ����ȴ����ӽ��̺�pid>0�����뱻ɨ���ӽ���p��pid����ȣ�˵�����ǵ�ǰ�����������
// ���̣����������ý��̣�����ɨ����һ�����̡�
380 if (pid>0) {
381 if (p->pid != pid)
382 continue;
// �������ָ���ȴ����̵�pid=0����ʾ���ڵȴ�������ŵ��ڵ�ǰ������ŵ��κ��ӽ��̡�
// �����ʱ��ɨ�����p�Ľ�������뵱ǰ���̵���Ų��ȣ���������
383 } else if (!pid) {
384 if (p->pgrp != current->pgrp)
385 continue;
// �������ָ����pid < -1����ʾ���ڵȴ�������ŵ���pid����ֵ���κ��ӽ��̡������ʱ
// ��ɨ�����p�������pid�ľ���ֵ���ȣ���������
386 } else if (pid != -1) {
387 if (p->pgrp != -pid)
388 continue;
389 }
// ���ǰ3����pid���ж϶������ϣ����ʾ��ǰ�������ڵȴ����κ��ӽ��̣�Ҳ��pid = -1
// ���������ʱ��ѡ�Ľ��� p ����������̺ŵ���ָ�� pid�������ǵ�ǰ�������е��κ�
// �ӽ��̣������ǽ��̺ŵ���ָ�� pid ����ֵ���ӽ��̣��������κ��ӽ��̣���ʱָ���� pid
// ���� -1������������������ӽ���p������״̬��������
// ���ӽ���p ����ֹͣ״̬ʱ�������ʱ����ѡ��options��WUNTRACED ��־û����λ����ʾ
// �����������̷��أ������ӽ��̴�ʱ���˳������ 0�����Ǽ���ɨ�账�������ӽ��̡� ���
// WUNTRACED��λ���ӽ����˳��벻Ϊ0������˳���������ֽڣ�����״̬��Ϣ 0x7f �����
// *stat_addr���ڸ�λ�ӽ����˳��������̷����ӽ��̺�pid������0x7f ��ʾ�ķ���״̬ʹ
// WIFSTOPPED()��Ϊ�档�μ�include/sys/wait.h��14�С�
390 switch (p->state) {
391 case TASK_STOPPED:
392 if (!(options & WUNTRACED) ||
393 !p->exit_code)
394 continue;
395 put_fs_long((p->exit_code << 8) | 0x7f,
396 stat_addr);
397 p->exit_code = 0;
398 return p->pid;
// ����ӽ���p���ڽ���״̬�������Ȱ������û�̬���ں�̬���е�ʱ��ֱ��ۼƵ���ǰ����
// �������̣��У�Ȼ��ȡ���ӽ��̵�pid���˳��룬���˳�����뷵��״̬λ��stat_addr��
// ���ͷŸ��ӽ��̡�����ӽ��̵��˳����pid�� �������˵��Խ��������ţ�����ý���
// �������ʾ������
399 case TASK_ZOMBIE:
400 current->cutime += p->utime;
401 current->cstime += p->stime;
402 flag = p->pid;
403 put_fs_long(p->exit_code, stat_addr);
404 release(p);
405 #ifdef DEBUG_PROC_TREE
406 audit_ptree();
407 #endif
408 return flag;
// �������ӽ���p��״̬�Ȳ���ֹͣҲ���ǽ�������ô����flag = 1����ʾ�ҵ���һ������
// Ҫ����ӽ��̣���������������̬��˯��̬��
409 default:
410 flag=1;
411 continue;
412 }
413 }
// ���������������ɨ���������� flag����λ��˵���з��ϵȴ�Ҫ����ӽ��̲�û�д�
// ���˳�����״̬����ʱ���������WNOHANGѡ���ʾ��û���ӽ��̴����˳�����ֹ̬��
// ���̷��أ��������̷���0���˳�������ѵ�ǰ������Ϊ���жϵȴ�״̬������������
// ��ǰ�����ź�����λͼ����������յ�SIGCHLD�źš�Ȼ��ִ�е��ȳ���ϵͳ�ֿ�ʼ
// ִ�б�����ʱ������������յ���SIGCHLD���������δ�����źţ������˳��롰������
// ��ϵͳ���á����ء�������ת��������ʼ��repeat��Ŵ��ظ�������
414 if (flag) {
415 if (options & WNOHANG)
416 return 0;
417 current->state=TASK_INTERRUPTIBLE;
418 oldblocked = current->blocked;
419 current->blocked &= ~(1<<(SIGCHLD-1));
420 schedule();
421 current->blocked = oldblocked;
422 if (current->signal & ~(current->blocked | (1<<(SIGCHLD-1))))
423 return -ERESTARTSYS;
424 else
425 goto repeat;
426 }
// ��flag = 0����ʾû���ҵ�����Ҫ����ӽ��̣��س����루�ӽ��̲����ڣ���
427 return -ECHILD;
428 }
429