linux内核中的信号机制--信号处理
时间:11-22
来源:互联网
点击:
返回后就不复存在了)。而现在必须通过最初的pt_regs上下文返回用户态,为此,在构建临时堆栈环境时,内核会把最初的pt_regs上下文备份到临时堆栈中(位于用户态堆栈),当通过系统调用sys_sigreturn()再次进入内核时,内核从用户态空间还原出原始的pt_regs。最后正常返回。
通过上面的讨论,我们知道在这个迂回的处理过程中,关键在于用户态的临时堆栈环境的建立,这是一个sigframe结构:
[plain]view plaincopyprint?
- /*
- *Doasignalreturn;undothesignalstack.Thesearealignedto64-bit.
- */
- structsigframe{
- structsigcontextsc;//保存一组寄存器上下文
- unsignedlongextramask[_NSIG_WORDS-1];
- unsignedlongretcode;//保存返回地址
- structaux_sigframeaux__attribute__((aligned(8)));
- };
- structrt_sigframe{
- structsiginfo__user*pinfo;
- void__user*puc;
- structsiginfoinfo;
- structucontextuc;
- unsignedlongretcode;
- structaux_sigframeaux__attribute__((aligned(8)));
- };
[plain]view plaincopyprint?
- staticinlinevoid__user*
- get_sigframe(structk_sigaction*ka,structpt_regs*regs,intframesize)
- {
- unsignedlongsp=regs->ARM_sp;
- void__user*frame;
- /*
- *ThisistheX/Opensanctionedsignalstackswitching.
- */
- if((ka->sa.sa_flags&SA_ONSTACK)&&!sas_ss_flags(sp))
- sp=current->sas_ss_sp+current->sas_ss_size;
- /*
- *ATPCSB01mandates8-bytealignment
- */
- frame=(void__user*)((sp-framesize)&~7);
- /*
- *Checkthatwecanactuallywritetothesignalframe.
- */
- if(!access_ok(VERIFY_WRITE,frame,framesize))
- frame=NULL;
- returnframe;
- }
通过上面的讨论,我们再回到do_signal()中来,如果有用户态的信号处理函数,do_signal()会调用handle_signal(),handle_signal()将调用setup_frame()或者setup_rt_frame()来完成实际的工作,这里我们以setup_frame()为例进行进一步讨论。
[plain]view plaincopyprint?
- staticint
- setup_frame(intusig,structk_sigaction*ka,sigset_t*set,structpt_regs*regs)
- {
- //在用户态堆栈上分配一个sigframe结构
- structsigframe__user*frame=get_sigframe(ka,regs,sizeof(*frame));
- interr=0;
- if(!frame)
- return1;
- //把相关信息从内核态备份到用户态堆栈的sigframe结构中
- err|=setup_sigcontext(&frame->sc,&frame->aux,regs,set->sig[0]);
- if(_NSIG_WORDS>1){
- err|=__copy_to_user(frame->extramask,&set->sig[1],
- sizeof(frame->extramask));
- }
- if(err==0)
- err=setup_return(regs,ka,&frame->retcode,frame,usig);
- returnerr;
- }
[plain]view plaincopyprint?
- staticint
- setup_return(structpt_regs*regs,structk_sigaction*ka,
- unsignedlong__user*rc,void__user*frame,intusig)
- {
- unsignedlonghandler=(unsignedlong)ka->sa.sa_handler;
- unsignedlongretcode;
- intthumb=0;
- unsignedlongcpsr=regs->ARM_cpsr&~PSR_f;
- /*
- *Maybeweneedtodelivera32-bitsignaltoa26-bittask.
- */
- if(ka->sa.sa_flags&SA_THIRTYTWO)
- cpsr=(cpsr&~MODE_MASK)|USR_MODE;
- #ifdefCONFIG_ARM_THUMB
- if(elf_hwcap&HWCAP_THUMB){
- /*
- *TheLSBofthehandlerdeterminesifweregoingto
- *beusingTHUMBorARMmodeforthissignalhandler.
- */
- thumb=handler&1;
- if(thumb)
- cpsr|=PSR_T_BIT;
- else
- cpsr&=~PSR_T_BIT;
- }
- #endif
- //这里的retcode就是保存手工构造的sigreturn()代码
- if(ka->sa.sa_flags&SA_RESTORER){
- retcode=(unsignedlong)ka->sa.sa_restorer;
- }else{
- unsignedintidx=thumb;
- if(ka->sa.sa_flags&SA_SIGINFO)
- idx+=2;
- if(__put_user(sigreturn_codes[idx],rc))
- return1;
- if(cpsr&MODE32_BIT){
- /*
- *32-bitcodecanusethenewhigh-page
- *signalreturncodesupport.
- */
- retcode=KERN_SIGRETURN_CODE+(idx<2)+thumb;
- }else{
- /*
- *Ensurethattheinstructioncachesees
- *thereturncodewrittenontothestack.
- */
- flush_icache_range((unsignedlong)rc,
- (unsignedlong)(rc+1));
- retcode=((unsignedlong)rc)+thumb;
- }
- }
- regs->ARM_r0=usig;
- regs->ARM_sp=(unsignedlong)frame;//堆栈
- regs->regs->ARM_lr=retcode;//返回地址,当
linux内核信号机制信号处 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)