《linux 内核完全剖析》 signal.c 代码分析笔记

来源:互联网 发布:中国交通地图软件 编辑:程序博客网 时间:2024/05/17 17:44

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*/}











0 0