����8-7 linux/kernel/exit.c


  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