/* * linux/kernel/signal.c * * (C) 1991 Linus Torvalds */
#include <linux/sched.h> #include <linux/kernel.h> #include <asm/segment.h>
#include <signal.h>
volatile void do_exit(int error_code);//volatile,告诉GCC编译器本函数不会返回
int sys_sgetmask()//取本进程任务信号屏蔽位
{ return current->blocked; }
int sys_ssetmask(int newmask)//设置本进程任务信号屏蔽位
{ int old=current->blocked;
current->blocked = newmask & ~(1<<(SIGKILL-1));//SIGKILL信号不可屏蔽
return old; }
static inline void save_old(char * from,char * to)//COPY sigaction 数据到FS段的TO处,从内核空间COPY到用户空间
{ int i;
verify_area(to, sizeof(struct sigaction));//验证目的地址的空间是否足够大
for (i=0 ; i< sizeof(struct sigaction) ; i++) { put_fs_byte(*from,to);//COPY
from++; to++; } }
static inline void get_new(char * from,char * to)//COPY sigaction 数据从FS段FROM地址到TO处,从用户空间到内核空间
{ int i;
for (i=0 ; i< sizeof(struct sigaction) ; i++) *(to++) = get_fs_byte(from++);//COPY
}
int sys_signal(int signum, long handler, long restorer)//为指定信号安装处理函数,signum为信号,handler为处理函数,restorer为恢复指针由LIBC库提供
{ struct sigaction tmp;
if (signum<1 || signum>32 || signum==SIGKILL)//最大为32个信号 ,不可为SIGKILL SIGSTOP这两个信号 不可为进程捕获
return -1; tmp.sa_handler = (void (*)(int)) handler; tmp.sa_mask = 0; tmp.sa_flags = SA_ONESHOT | SA_NOMASK;////SA_NOCLDSTOP,SA_NOMASK,SA_ONESHOT
tmp.sa_restorer = (void (*)(void)) restorer; handler = (long) current->sigaction[signum-1].sa_handler;//保存当前任务以前此信号处理函数
current->sigaction[signum-1] = tmp;//定义当前任务此信号 的处理函数
return handler; }
int sys_sigaction(int signum, const struct sigaction * action, struct sigaction * oldaction)//修改进程在收到一个信号 时的操作,相关操作同前
{ struct sigaction tmp;
if (signum<1 || signum>32 || signum==SIGKILL) return -1; tmp = current->sigaction[signum-1]; get_new((char *) action, (char *) (signum-1+current->sigaction));//COPY sigaction 数据从FS段FROM地址到TO处,从用户空间到内核空间
if (oldaction) save_old((char *) &tmp,(char *) oldaction);//COPY sigaction 数据从FS段FROM地址到TO处,从用户空间到内核空间
if (current->sigaction[signum-1].sa_flags & SA_NOMASK)//允许信号在自己的信号句柄中收到
current->sigaction[signum-1].sa_mask = 0; else current->sigaction[signum-1].sa_mask |= (1<<(signum-1)); return 0; }
void do_signal(long signr,long eax, long ebx, long ecx, long edx, long fs, long es, long ds, long eip, long cs, long eflags, unsigned long * esp, long ss)//内核系统调用 (int 0X80)中断处理程序中对信号的预处理程序,由/kernel/system_call.s line 119行调用,本函数主要作用为:将信号处理函数放入用户椎栈,本函数调用返回时可保证立即执行信号处理函数,然后继续执行用用户的程序
{ unsigned long sa_handler; long old_eip=eip; struct sigaction * sa = current->sigaction + signr - 1;//current->sigaction[signr-1]
int longs; unsigned long * tmp_esp;
sa_handler = (unsigned long) sa->sa_handler;//取得句柄,0为SIG_DFL, 1为SIG_IGN, 其他为用户定义的信号处理函数
if (sa_handler==1)//如果为SIG_IGN,则忽落返回
return; if (!sa_handler) { if (signr==SIGCHLD)//如果为SIGCHLD则也返回
return; else//其他的则退出返回
do_exit(1<<(signr-1));//可作为wait() waitpid() 函数的 状态信息,/include/sys/wait.h
} if (sa->sa_flags & SA_ONESHOT) sa->sa_handler = NULL; *(&eip) = sa_handler; longs = (sa->sa_flags & SA_NOMASK)?7:8; *(&esp) -= longs; verify_area(esp,longs*4); tmp_esp=esp; put_fs_long((long) sa->sa_restorer,tmp_esp++); put_fs_long(signr,tmp_esp++); if (!(sa->sa_flags & SA_NOMASK)) put_fs_long(current->blocked,tmp_esp++); put_fs_long(eax,tmp_esp++); put_fs_long(ecx,tmp_esp++); put_fs_long(edx,tmp_esp++); put_fs_long(eflags,tmp_esp++); put_fs_long(old_eip,tmp_esp++); current->blocked |= sa->sa_mask;//进程信号屏蔽码
}
|