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