����8-6 linux/kernel/signal.c


  1 /*

  2  *  linux/kernel/signal.c

  3  *

  4  *  (C) 1991  Linus Torvalds

  5  */

  6

  7 #include <linux/sched.h>  // ���ȳ���ͷ�ļ�����������ṹtask_struct����ʼ����0�����ݣ�

                              // ����һЩ�й��������������úͻ�ȡ��Ƕ��ʽ��ຯ������䡣

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

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

 10

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

 12 #include <errno.h>        // ������ͷ�ļ�����������ŷ��ų�����

 13  

    // ��ȡ��ǰ�����ź�����λͼ��������������룩��sgetmask�ɷֽ�Ϊsignal-get-mask���������ơ�

 14 int sys_sgetmask()

 15 {

 16         return current->blocked;

 17 }

 18

    // �����µ��ź�����λͼ���ź�SIGKILL��SIGSTOP���ܱ����Ρ�����ֵ��ԭ�ź�����λͼ��

 19 int sys_ssetmask(int newmask)

 20 {

 21         int old=current->blocked;

 22

 23         current->blocked = newmask & ~(1<<(SIGKILL-1)) & ~(1<<(SIGSTOP-1));

 24         return old;

 25 }

 26

    // ��Ⲣȡ�ý����յ��ĵ������Σ����������źš���δ�����źŵ�λͼ��������set�С�

 27 int sys_sigpending(sigset_t *set)

 28 {

 29     /* fill in "set" with signals pending but blocked. */

        /* �û�δ�������ұ������źŵ�λͼ����setָ����ָλ�ô� */

    // ������֤�����ṩ���û��洢�ռ�Ӧ��4���ֽڡ�Ȼ��ѻ�δ�������ұ������źŵ�λͼ����

    // setָ����ָλ�ô���

 30     verify_area(set,4);

 31     put_fs_long(current->blocked & current->signal, (unsigned long *)set);

 32     return 0;

 33 }

 34

 35 /* atomically swap in the new signal mask, and wait for a signal.

 36  *

 37  * we need to play some games with syscall restarting.  We get help

 38  * from the syscall library interface.  Note that we need to coordinate

 39  * the calling convention with the libc routine.

 40  *

 41  * "set" is just the sigmask as described in 1003.1-1988, 3.3.7.

 42  *      It is assumed that sigset_t can be passed as a 32 bit quantity.

 43  *

 44  * "restart" holds a restart indication.  If it's non-zero, then we

 45  *      install the old mask, and return normally.  If it's zero, we store

 46  *      the current mask in old_mask and block until a signal comes in.

 47  */

    /* �Զ��ظ������µ��ź������룬���ȴ��źŵĵ�����

     *

     * ������Ҫ��ϵͳ���ã�syscall����һЩ���������ǻ��ϵͳ���ÿ�ӿ�ȡ��ijЩ��Ϣ��

     * ע�⣬������Ҫ�ѵ��ù�����libc���е��ӳ���ͳһ���ǡ�

     *

     * "set" ����POSIX��׼1003.1-1988��3.3.7�������������ź�������sigmask��

     *       ������Ϊ����sigset_t�ܹ���Ϊһ��32λ�����ݡ�

     *

     * "restart"�б���������ָʾ��־�����Ϊ��0ֵ����ô���Ǿ�����ԭ���������룬

     *       �����������ء������Ϊ0����ô���ǾͰѵ�ǰ�������뱣����oldmask��

     *       �����������̣�ֱ���յ��κ�һ���ź�Ϊֹ��

     */

    // ��ϵͳ������ʱ�ѽ����ź��������滻�ɲ����и�����set��Ȼ�������̣�ֱ���յ�һ��

    // �ź�Ϊֹ��

    // restart��һ�����жϵ�ϵͳ��������������־������1�ε��ø�ϵͳ����ʱ������0������

    // �ڸú����л�ѽ���ԭ���������� blocked����������old_mask���������� restartΪ��0

    // ֵ����˵����̵�2�ε��ø�ϵͳ����ʱ�����ͻ�ָ�����ԭ��������old_mask�е������롣

 48 int sys_sigsuspend(int restart, unsigned long old_mask, unsigned long set)

 49 {

    // pause()ϵͳ���ý����µ������Ľ��̽���˯��״̬��ֱ���յ�һ���źš����źŻ��߻���ֹ

    // ���̵�ִ�У����ߵ��½���ȥִ����Ӧ���źŲ�������

 50     extern int sys_pause(void);

 51

    // ���restart��־��Ϊ0����ʾ�������ó����������������ǻָ�ǰ�汣����old_mask�е�

    // ԭ���������롣��������-EINTR��ϵͳ���ñ��ź��жϣ���

 52     if (restart) {

 53         /* we're restarting */       /* ����������������ϵͳ���� */

 54         current->blocked = old_mask;

 55         return -EINTR;

 56     }

    // �����ʾrestart��־��ֵ��0����ʾ��1�ε��á�������������restart��־����Ϊ1����

    // ������̵�ǰ������ blocked �� old_mask�У����ѽ��̵��������滻�� set��Ȼ�����

    // pause()�ý���˯�ߣ��ȴ��źŵĵ������������յ�һ���ź�ʱ��pause() �ͻ᷵�أ�����

    // ���̻�ȥִ���źŴ���������Ȼ�󱾵��÷��� -ERESTARTNOINTR ���˳������������˵��

    // �ڴ������źź�Ҫ�󷵻ص���ϵͳ�����м������У�����ϵͳ���ò��ᱻ�жϡ�

 57     /* we're not restarting.  do the work */

        /* ���Dz��������������У���ô�͸ɻ�� */

 58     *(&restart) = 1;

 59     *(&old_mask) = current->blocked;

 60     current->blocked = set;

 61     (void) sys_pause();                 /* return after a signal arrives */

 62     return -ERESTARTNOINTR;             /* handle the signal, and come back */

 63 }

 64

    // ����sigaction���ݵ�fs���ݶ�to���������ں˿ռ临�Ƶ��û����������ݶ��С�

 65 static inline void save_old(char * from,char * to)

 66 {

 67         int i;

 68

    // ������֤to�����ڴ�ռ��Ƿ��㹻��Ȼ���һ��sigaction�ṹ��Ϣ���Ƶ�fs�Σ��û���

    // �ռ��С��꺯��put_fs_byte()��include/asm/segment.h��ʵ�֡�

 69         verify_area(to, sizeof(struct sigaction));

 70         for (i=0 ; i< sizeof(struct sigaction) ; i++) {

 71                 put_fs_byte(*from,to);

 72                 from++;

 73                 to++;

 74         }

 75 }

 76

    // ��sigaction���ݴ�fs���ݶ�fromλ�ø��Ƶ�to���������û����ݿռ�ȡ���ں����ݶ��С�

 77 static inline void get_new(char * from,char * to)

 78 {

 79         int i;

 80

 81         for (i=0 ; i< sizeof(struct sigaction) ; i++)

 82                 *(to++) = get_fs_byte(from++);

 83 }

 84

    // signal()ϵͳ���á�������sigaction()��Ϊָ�����źŰ�װ�µ��źž��(�źŴ�������)��

    // �źž���������û�ָ���ĺ�����Ҳ������SIG_DFL��Ĭ�Ͼ������SIG_IGN�����ԣ���

    // ����signum --ָ�����źţ�handler -- ָ���ľ����restorer �C�ָ�����ָ�룬�ú�����

    // Libc ���ṩ���������źŴ������������ָ�ϵͳ���÷���ʱ�����Ĵ�����ԭ��ֵ�Լ�ϵͳ

    // ���õķ���ֵ���ͺ���ϵͳ����û��ִ�й��źŴ��������ֱ�ӷ��ص��û�����һ���� ����

    // ����ԭ�źž����

 85 int sys_signal(int signum, long handler, long restorer)

 86 {

 87         struct sigaction tmp;

 88

    // ������֤�ź�ֵ����Ч��Χ��1--32���ڣ����Ҳ������ź�SIGKILL����SIGSTOP������Ϊ��

    // �����źŲ��ܱ����̲���

 89         if (signum<1 || signum>32 || signum==SIGKILL || signum==SIGSTOP)

 90                 return -EINVAL;

    // Ȼ������ṩ�IJ����齨sigaction�ṹ���ݡ�sa_handler��ָ�����źŴ����������������

    // sa_mask��ִ���źŴ������ʱ���ź������롣sa_flags��ִ��ʱ��һЩ��־��ϡ������趨

    // ���źŴ������ֻʹ��1�κ�ͻָ���Ĭ��ֵ���������ź����Լ��Ĵ���������յ���

 91         tmp.sa_handler = (void (*)(int)) handler;

 92         tmp.sa_mask = 0;

 93         tmp.sa_flags = SA_ONESHOT | SA_NOMASK;

 94         tmp.sa_restorer = (void (*)(void)) restorer;      // ����ָ���������ָ�롣

    // ����ȡ���ź�ԭ���Ĵ�������������ø��źŵ�sigaction�ṹ����󷵻�ԭ�źž����

 95         handler = (long) current->sigaction[signum-1].sa_handler;

 96         current->sigaction[signum-1] = tmp;

 97         return handler;

 98 }

 99

    // sigaction()ϵͳ���á��ı�������յ�һ���ź�ʱ�IJ�����signum�dz���SIGKILL�����

    // �κ��źš�[����²�����action����Ϊ�� ]���²�������װ����� oldactionָ�벻Ϊ�գ�

    // ��ԭ������������oldaction���ɹ��򷵻�0������Ϊ-EINVAL��

100 int sys_sigaction(int signum, const struct sigaction * action,

101         struct sigaction * oldaction)

102 {

103         struct sigaction tmp;

104

    // ������֤�ź�ֵ����Ч��Χ��1--32���ڣ����Ҳ������ź�SIGKILL����SIGSTOP������Ϊ��

    // �����źŲ��ܱ����̲���

105         if (signum<1 || signum>32 || signum==SIGKILL || signum==SIGSTOP)

106                 return -EINVAL;

    // ���źŵ�sigaction�ṹ�������µIJ����������������oldactionָ�벻Ϊ�յĻ�����

    // ԭ����ָ�뱣�浽oldaction��ָ��λ�á�

107         tmp = current->sigaction[signum-1];

108         get_new((char *) action,

109                 (char *) (signum-1+current->sigaction));

110         if (oldaction)

111                 save_old((char *) &tmp,(char *) oldaction);

    // ��������ź����Լ����źž�����յ�������������Ϊ0�������������α��źš�

112         if (current->sigaction[signum-1].sa_flags & SA_NOMASK)

113                 current->sigaction[signum-1].sa_mask = 0;

114         else

115                 current->sigaction[signum-1].sa_mask |= (1<<(signum-1));

116         return 0;

117 }

118

119 /*

120  * Routine writes a core dump image in the current directory.

121  * Currently not implemented.

122  */

    /*

     * �ڵ�ǰĿ¼�в���core dumpӳ���ļ����ӳ���Ŀǰ��û��ʵ�֡�

     */

123 int core_dump(long signr)

124 {

125         return(0);      /* We didn't do a dump */

126 }

127

    // ϵͳ���õ��жϴ����������������ź�Ԥ����������kernel/sys_call.s,119�У������

    // �������Ҫ�����ǽ��źŴ���������뵽�û������ջ�У����ڱ�ϵͳ���ý������غ�����

    // ִ���źž������Ȼ�����ִ���û��ij���

    // �����IJ����ǽ���ϵͳ���ô�������sys_call.s��ʼ��ֱ�����ñ�������sys_call.s

    // ��125�У�ǰ��ѹ���ջ��ֵ����Щֵ��������sys_call.s�еĴ����У���

    // �� CPUִ���ж�ָ��ѹ����û�ջ��ַss��esp����־�Ĵ���eflags�ͷ��ص�ַcs��eip��

    // �� ��85--91���ڸս���system_callʱѹ��ջ�ĶμĴ���ds��es��fs�Լ��Ĵ���eax

    // ��orig_eax����edx��ecx��ebx��ֵ��

    // �� ��100�е���sys_call_table��ѹ��ջ�е���Ӧϵͳ���ô��������ķ���ֵ��eax����

    // �� ��124��ѹ��ջ�еĵ�ǰ�������ź�ֵ��signr����

128 int do_signal(long signr,long eax,long ebx, long ecx, long edx, long orig_eax,

129         long fs, long es, long ds,

130         long eip, long cs, long eflags,

131         unsigned long * esp, long ss)

132 {

133         unsigned long sa_handler;

134         long old_eip=eip;

135         struct sigaction * sa = current->sigaction + signr - 1;

136         int longs;                                // �� current->sigaction[signr-1]��

137

138         unsigned long * tmp_esp;

139

    // �����ǵ�����䡣��������notdefʱ���ӡ�����Ϣ��

140 #ifdef notdef

141         printk("pid: %d, signr: %x, eax=%d, oeax = %d, int=%d\n",

142                 current->pid, signr, eax, orig_eax,

143                 sa->sa_flags & SA_INTERRUPT);

144 #endif

    // �������ϵͳ���ö��������ж�ִ�й����е��õ�������ʱ��  roig_eax ֵΪ -1�� �μ�

    // sys_call.s ��144�� ����䡣��˵� orig_eax������ -1 ʱ��˵������ij��ϵͳ���õ�

    // �������˱��������� kernel/exit.c �� waitpid() �����У�����յ���SIGCHLD �źţ�

    // �����ڶ��ܵ�����fs/pipe.c�йܵ���ǰ�����ݵ�û�ж����κ����ݵ�����£������յ�

    // ���κ�һ�����������źţ��򶼻��� -ERESTARTSYS ����ֵ���ء�����ʾ���̿��Ա��жϣ�

    // �����ڼ���ִ�к����������ϵͳ���á�������-ERESTARTNOINTR˵���ڴ������źź�Ҫ��

    // ���ص�ԭϵͳ�����м������У���ϵͳ���ò��ᱻ�жϡ��μ�ǰ���62�С�

    // ����������˵���������ϵͳ�����е��õı�������������Ӧϵͳ���õķ����� eax����

    // -ERESTARTSYS�� -ERESTARTNOINTRʱ��������Ĵ�����ʵ���ϻ�û�������ص��û������У���

145         if ((orig_eax != -1) &&

146             ((eax == -ERESTARTSYS) || (eax == -ERESTARTNOINTR))) {

    // ���ϵͳ���÷������� -ERESTARTSYS����������ϵͳ���ã������� sigaction �к��б�־

    // SA_INTERRUPT��ϵͳ���ñ��ź��жϺ���������ϵͳ���ã������ź�ֵС�� SIGCONT����

    // �ź�ֵ����SIGTTOU�����źŲ���SIGCONT��SIGSTOP��SIGTSTP��SIGTTIN ��SIGTTOU������

    // �޸�ϵͳ���õķ���ֵΪeax = -EINTR�������ź��жϵ�ϵͳ���á�

147                 if ((eax == -ERESTARTSYS) && ((sa->sa_flags & SA_INTERRUPT) ||

148                     signr < SIGCONT || signr > SIGTTOU))

149                         *(&eax) = -EINTR;

150                 else {

    // ����ͻָ����̼Ĵ���eax�ڵ���ϵͳ����֮ǰ��ֵ�����Ұ�ԭ����ָ��ָ��ص�2�ֽڡ���

    // �������û�����ʱ���ó�����������ִ�б��ź��жϵ�ϵͳ���á�

151                         *(&eax) = orig_eax;

152                         *(&eip) = old_eip -= 2;

153                 }

154         }

    // ����źž��ΪSIG_IGN��1��Ĭ�Ϻ��Ծ�����򲻶��źŽ��д�����ֱ�ӷ��ء�

155         sa_handler = (unsigned long) sa->sa_handler;

156         if (sa_handler==1)

157                 return(1);   /* Ignore, see if there are more signals... */

    // ������ΪSIG_DFL��0��Ĭ�ϴ�����������ݾ�����źŽ��зֱ�����

158         if (!sa_handler) {

159                 switch (signr) {

    // ����ź�������������Ҳ����֮�������ء�

160                 case SIGCONT:

161                 case SIGCHLD:

162                         return(1);  /* Ignore, ... */

163

    // ����ź�������4���ź�֮һ����ѵ�ǰ����״̬��Ϊֹͣ״̬TASK_STOPPED������ǰ����

    // �����̶�SIGCHLD�źŵ� sigaction������־ SA_NOCLDSTOP �������ӽ���ִֹͣ�л��ּ�

    // ��ִ��ʱ��Ҫ����SIGCHLD�źţ�û����λ����ô�͸������̷���SIGCHLD�źš�

164                 case SIGSTOP:

165                 case SIGTSTP:

166                 case SIGTTIN:

167                 case SIGTTOU:

168                         current->state = TASK_STOPPED;

169                         current->exit_code = signr;

170                         if (!(current->p_pptr->sigaction[SIGCHLD-1].sa_flags &

171                                         SA_NOCLDSTOP))

172                                 current->p_pptr->signal |= (1<<(SIGCHLD-1));

173                         return(1);  /* Reschedule another event */

174

    // ����ź�������6���ź�֮һ����ô���źŲ�����core dump�������˳���Ϊsignr|0x80

    // ����do_exit()�˳��������˳�������ź�ֵ��do_exit()�IJ����Ƿ�����ͳ����ṩ���˳�

    // ״̬��Ϣ������Ϊwait()��waitpid()������״̬��Ϣ���μ�sys/wait.h�ļ���13-18�С�

    // wait()��waitpid()������Щ��Ϳ���ȡ���ӽ��̵��˳�״̬����ӽ�����ֹ��ԭ���źţ���

175                 case SIGQUIT:

176                 case SIGILL:

177                 case SIGTRAP:

178                 case SIGIOT:

179                 case SIGFPE:

180                 case SIGSEGV:

181                         if (core_dump(signr))

182                                 do_exit(signr|0x80);

183                         /* fall through */

184                 default:

185                         do_exit(signr);

186                 }

187         }

188         /*

189          * OK, we're invoking a handler

190          */

            /*

             * OK����������׼�����źž�����õ�����

             */

    // ������źž��ֻ�豻����һ�Σ��򽫸þ���ÿա�ע�⣬���źž����ǰ���Ѿ�������

    // sa_handlerָ���С�

    // ��ϵͳ���ý����ں�ʱ���û����򷵻ص�ַ��eip��cs�����������ں�̬ջ�С�������δ�

    // ���޸��ں�̬��ջ���û�����ϵͳ����ʱ�Ĵ���ָ�� eip Ϊָ���źŴ��������ͬʱҲ��

    // sa_restorer��signr������������(���SA_NOMASKû��λ)��eax��ecx��edx��Ϊ�����Լ�

    // ԭ����ϵͳ���õij��򷵻�ָ�뼰��־�Ĵ���ֵѹ���û���ջ�� ����ڱ���ϵͳ�����ж�

    // �����û�����ʱ������ִ���û����źž������Ȼ���ټ���ִ���û�����

191         if (sa->sa_flags & SA_ONESHOT)

192                 sa->sa_handler = NULL;

    // ���ں�̬ջ���û�����ϵͳ������һ������ָ��ָ��eipָ����źŴ������������C����

    // �Ǵ�ֵ��������˸�eip��ֵʱ��Ҫʹ�� "*(&eip)" ����ʽ�����⣬��������ź��Լ���

    // ��������յ��ź��Լ�����Ҳ��Ҫ�����̵�������ѹ���ջ��

    // ������ע�⣬ʹ�����·�ʽ����193�У�����ͨC�������������޸��Dz������õġ���Ϊ��

    // ��������ʱ��ջ�ϵIJ������ᱻ�����߶���������֮���Կ���ʹ�����ַ�ʽ������Ϊ�ú���

    // �Ǵӻ������б����õģ������ں������غ������û�аѵ���do_signal()ʱ������

    // ������������eip����Ȼ�ڶ�ջ�С�

    // sigaction�ṹ��sa_mask�ֶθ������ڵ�ǰ�źž�����ź�������������ִ���ڼ�Ӧ�ñ�

    // ���ε��źż���ͬʱ�������źž��ִ�е��ź�Ҳ�ᱻ���Ρ� ������sa_flags��ʹ����

    // SA_NOMASK��־����ô�����źž��ִ�е��źŽ����ᱻ���ε�����������ź��Լ��Ĵ�

    // ����������յ��ź��Լ�����Ҳ��Ҫ�����̵��ź�������ѹ���ջ��

193         *(&eip) = sa_handler;

194         longs = (sa->sa_flags & SA_NOMASK)?7:8;

    // ��ԭ���ó�����û���ջָ��������չ7����8�������֣�������ŵ����źž���IJ����ȣ���

    // ������ڴ�ʹ���������������ڴ泬���������ҳ�ȣ���

195         *(&esp) -= longs;

196         verify_area(esp,longs*4);

    // ���û���ջ�д��µ��ϴ��sa_restorer���ź�signr��������blocked�����SA_NOMASK

    // ��λ����eax��ecx��edx��eflags���û�����ԭ����ָ�롣

197         tmp_esp=esp;

198         put_fs_long((long) sa->sa_restorer,tmp_esp++);

199         put_fs_long(signr,tmp_esp++);

200         if (!(sa->sa_flags & SA_NOMASK))

201                 put_fs_long(current->blocked,tmp_esp++);

202         put_fs_long(eax,tmp_esp++);

203         put_fs_long(ecx,tmp_esp++);

204         put_fs_long(edx,tmp_esp++);

205         put_fs_long(eflags,tmp_esp++);

206         put_fs_long(old_eip,tmp_esp++);

207         current->blocked |= sa->sa_mask;   // ����������(������)����sa_mask�е���λ��

208         return(0);              /* Continue, execute handler */

209 }

210