《linux 内核完全剖析》 signal.c 代码分析笔记
signal.c 代码分析笔记
sgetmask
int sys_sgetmask()// 获取当前进程阻塞的信号
{
returncurrent->blocked;
}
sys_ssetmask
int sys_ssetmask(int newmask) //设置当前进程阻塞信号,确保SIGKILL 和SIGSTOP不被阻塞
{
int old=current->blocked;
current->blocked= newmask & ~(1<<(SIGKILL-1)) & ~(1<<(SIGSTOP-1));
return old;
}
sys_sigpending
int sys_sigpending(sigset_t *set)//verify_area的水有点深。嘿嘿。。。
{
/* fill in "set" with signals pending but blocked. */
verify_area(set,4); //验证set指向的地址处4字节是否可写,不可写就给他分配一页内存,并给与读写权限。。。。
put_fs_long(current->blocked & current->signal, (unsigned long*)set); //这里理解成把第一个参数的值赋值给set指向的地址就好。。。。
return 0;
}
put_fs_byte
extern inline void put_fs_byte(charval,char *addr)
{
__asm__ ("movb%0,%%fs:%1"::"r" (val),"m" (*addr));
}
需要说明的就是这里fs寄存器是指向LDT的数据段描述符0x17,即fs用于访问数据
sys_sigsuspend
int sys_sigsuspend(int restart, unsignedlong old_mask, unsigned long set)
{
extern int sys_pause(void); //声明引用sys_pause
if (restart) {//如果restart 非零,进程的阻塞信号为old_mask
/*we‘re restarting */
current->blocked= old_mask;
return-EINTR;
}
//如果restart 非零
/* we‘re not restarting. do thework */
*(&restart) = 1;
*(&old_mask) = current->blocked; //把当前进程的阻塞信号做oldmask
//额。。。我不知道给一个局部变量赋值之后又不返回,先的函数也不引用这变量,
//这究竟有什么用!我必须质疑这是冗余的赋值操作
current->blocked = set;
(void) sys_pause(); /*return after a signal arrives */
//我不得不感叹,这个sys_pause就相当于sleep(很短的时间)
//这么做就是为了捕获信号
return -ERESTARTNOINTR; /*handle the signal, and come back */
}
save_old
static inline void save_old(char *from,char * to) //把内核段的数据copy到用户段(local date space)
{
inti;
verify_area(to,sizeof(struct sigaction)); //确保to地址处有结构体大小的内存可读写
for(i=0 ; i< sizeof(struct sigaction) ; i++) { //一个字节一个字节的copy,from到to
put_fs_byte(*from,to);
from++;
to++;
}
}
get_new
static inline void get_new(char * from,char* to)//把数据从用户段copy到内核数据段中
{
inti;
for(i=0 ; i< sizeof(struct sigaction) ; i++)
*(to++)= get_fs_byte(from++);
}
sys_signal
int sys_signal(int signum, long handler,long restorer)
{
structsigaction tmp;
if(signum<1 || signum>32 || signum==SIGKILL || signum==SIGSTOP)
//常规检测,signal必须在定义范围内,并且不能呢个为SIGKILL和SIGSTOP,否者直接结束
return-EINVAL;
tmp.sa_handler= (void (*)(int)) handler; //handler被强制转换成了一个函数指针,这个函数以int为参数,无返回
tmp.sa_mask= 0;//清空所有信号
tmp.sa_flags= SA_ONESHOT | SA_NOMASK;
tmp.sa_restorer= (void (*)(void)) restorer; //restorer被强制转换成一个函数指针,这个函数以int为参数,无返回
handler= (long) current->sigaction[signum-1].sa_handler;
current->sigaction[signum-1]= tmp; //结构体直接赋值
return handler;
}
sys_sigaction
int sys_sigaction(int signum, const structsigaction * action,
structsigaction * oldaction)
{
structsigaction tmp;
if(signum<1 || signum>32 || signum==SIGKILL || signum==SIGSTOP)
//常规检测,signal必须在定义范围内,并且不能呢个为SIGKILL和SIGSTOP,否者直接结束
return-EINVAL;
tmp= current->sigaction[signum-1];
get_new((char*) action,
(char*) (signum-1+current->sigaction)); //把只读的action结构体的信息写入到内核数据段
if(oldaction)
save_old((char*) &tmp,(char *) oldaction); //current进程原来的sigaction结构体信息
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)); //否则把signum 写入信号变量
return0;
}
do_signal
int do_signal(long signr,long eax,long ebx,long ecx, long edx, long orig_eax,
longfs, long es, long ds,
longeip, long cs, long eflags,
unsignedlong * esp, long ss)
{
unsignedlong sa_handler;
longold_eip=eip;
structsigaction * sa = current->sigaction + signr - 1;
int longs;
unsignedlong * tmp_esp;
#ifdef notdef
printk("pid:%d, signr: %x, eax=%d, oeax = %d, int=%d\n",
current->pid,signr, eax, orig_eax,
sa->sa_flags& SA_INTERRUPT); //打印相关信息
#endif
if((orig_eax != -1) && //如果不是系统调用而是其他中断执行过程中调用到本函数时,roig_eax 值为-1
((eax == -ERESTARTSYS) || (eax ==-ERESTARTNOINTR))) {
if((eax == -ERESTARTSYS) && ((sa->sa_flags & SA_INTERRUPT) ||
signr < SIGCONT || signr > SIGTTOU))
*(&eax)= -EINTR;
else{
*(&eax)= orig_eax;
*(&eip)= old_eip -= 2;//不明白为什么这里要回调两个byte
}
}
sa_handler= (unsigned long) sa->sa_handler;
if(sa_handler==1)
return(1); /* Ignore, see if there are more signals...*/
if(!sa_handler) { //sa_handler 为SIG_DFL 0
switch(signr) {
caseSIGCONT:
caseSIGCHLD:
return(1); /* Ignore, ... */
caseSIGSTOP:
caseSIGTSTP:
caseSIGTTIN:
caseSIGTTOU:
current->state= TASK_STOPPED;
//SIGSTOP SIGTSTP SIGTTIN SIGTTOU 被捕捉了,那么把当前进程置为停止状态
current->exit_code= signr;
if(!(current->p_pptr->sigaction[SIGCHLD-1].sa_flags &
SA_NOCLDSTOP))// 如果parent process 不允许child process stop
current->p_pptr->signal|= (1<<(SIGCHLD-1)); //告诉parent ,child process 挂掉了
return(1); /* Reschedule another event */
caseSIGQUIT:
caseSIGILL:
caseSIGTRAP:
caseSIGIOT:
caseSIGFPE:
caseSIGSEGV:
if(core_dump(signr))
do_exit(signr|0x80);
/*fall through */
default:
do_exit(signr);
}
}
/*
* OK, we‘re invoking a handler
*/
if(sa->sa_flags & SA_ONESHOT)
sa->sa_handler= NULL;
*(&eip)= sa_handler;
longs= (sa->sa_flags & SA_NOMASK)?7:8;
//堆栈指针向下偏移7 或者8 ,这时候 longs是 long型变量,esp也是,减去7,8也就是数值上的而已
//但是我没想明白这个78的单位是什么??? 这又不是指针,所以我就觉得很奇怪。。。。
*(&esp)-= longs;
verify_area(esp,longs*4);
tmp_esp=esp;
//各种从用户数据段copy到内核数据段
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;
return(0); /* Continue, execute handler*/
}
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。