<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > linux內(nèi)核中的信號(hào)機(jī)制--信號(hào)處理

          linux內(nèi)核中的信號(hào)機(jī)制--信號(hào)處理

          作者: 時(shí)間:2016-11-22 來(lái)源:網(wǎng)絡(luò) 收藏
          Kernel version:2.6.14

          CPU architecture:ARM920T

          本文引用地址:http://www.ex-cimer.com/article/201611/320006.htm

          Author:ce123(http://blog.csdn.net/ce123)

          當(dāng)進(jìn)程被調(diào)度時(shí),會(huì)調(diào)用do_notify_resume()來(lái)處理信號(hào)隊(duì)列中的信號(hào)。信號(hào)處理主要就是調(diào)用sighand_struct結(jié)構(gòu)中對(duì)應(yīng)的信號(hào)處理函數(shù)。do_notify_resume()(arch/arm/kernel/signal.c)函數(shù)的定義如下:

          [plain]view plaincopy
          print?
          1. asmlinkagevoid
          2. do_notify_resume(structpt_regs*regs,unsignedintthread_flags,intsyscall)
          3. {
          4. if(thread_flags&_TIF_SIGPENDING)
          5. do_signal(¤t->blocked,regs,syscall);
          6. }
          _TIF_SIGPENDING標(biāo)志是在signal_wake_up()函數(shù)中設(shè)置的,檢查該標(biāo)志后,接下來(lái)就調(diào)用do_signal()函數(shù),我們來(lái)看看do_signal()(arch/arm/kernel/signal.c)的具體定義:

          [plain]view plaincopy
          print?
          1. /*
          2. *Notethatinitisaspecialprocess:itdoesntgetsignalsitdoesnt
          3. *wanttohandle.ThusyoucannotkillinitevenwithaSIGKILLevenby
          4. *mistake.
          5. *
          6. *Notethatwegothroughthesignalstwice:oncetocheckthesignalsthat
          7. *thekernelcanhandle,andthenwebuildalltheuser-levelsignalhandling
          8. *stack-framesinonegoafterthat.
          9. */
          10. staticintdo_signal(sigset_t*oldset,structpt_regs*regs,intsyscall)
          11. {
          12. structk_sigactionka;
          13. siginfo_tinfo;
          14. intsignr;
          15. /*
          16. *Wewantthecommoncasetogofast,which
          17. *iswhywemayincertaincasesgetherefrom
          18. *kernelmode.Justreturnwithoutdoinganything
          19. *ifso.
          20. */
          21. if(!user_mode(regs))//regs保存的是進(jìn)入內(nèi)核態(tài)之前的寄存器現(xiàn)場(chǎng),必須為用戶(hù)模式,否則直接返回
          22. return0;
          23. if(try_to_freeze())
          24. gotono_signal;
          25. if(current->ptrace&PT_SINGLESTEP)
          26. ptrace_cancel_bpt(current);//和調(diào)試相關(guān),我們?cè)诤竺娴奈恼轮袝?huì)具體分析
          27. signr=get_signal_to_deliver(&info,&ka,regs,NULL);//取出等待處理的信號(hào)
          28. if(signr>0){
          29. handle_signal(signr,&ka,&info,oldset,regs,syscall);//處理信號(hào)
          30. if(current->ptrace&PT_SINGLESTEP)
          31. ptrace_set_bpt(current);
          32. return1;
          33. }
          34. no_signal:
          35. /*
          36. *Nosignaltodelivertotheprocess-restartthesyscall.
          37. */
          38. if(syscall){
          39. if(regs->ARM_r0==-ERESTART_RESTARTBLOCK){
          40. if(thumb_mode(regs)){
          41. regs->ARM_r7=__NR_restart_syscall;
          42. regs->ARM_pc-=2;
          43. }else{
          44. u32__user*usp;
          45. regs->ARM_sp-=12;
          46. usp=(u32__user*)regs->ARM_sp;
          47. put_user(regs->ARM_pc,&usp[0]);
          48. /*swi__NR_restart_syscall*/
          49. put_user(0xef000000|__NR_restart_syscall,&usp[1]);
          50. /*ldrpc,[sp],#12*/
          51. put_user(0xe49df00c,&usp[2]);
          52. flush_icache_range((unsignedlong)usp,
          53. (unsignedlong)(usp+3));
          54. regs->ARM_pc=regs->ARM_sp+4;
          55. }
          56. }
          57. if(regs->ARM_r0==-ERESTARTNOHAND||
          58. regs->ARM_r0==-ERESTARTSYS||
          59. regs->ARM_r0==-ERESTARTNOINTR){
          60. restart_syscall(regs);
          61. }
          62. }
          63. if(current->ptrace&PT_SINGLESTEP)
          64. ptrace_set_bpt(current);
          65. return0;
          66. }

          執(zhí)行do_signal()函數(shù)時(shí),進(jìn)程一定處于內(nèi)核空間,通常進(jìn)程只有通過(guò)中斷或者系統(tǒng)調(diào)用才能進(jìn)入內(nèi)核空間,regs保存著系統(tǒng)調(diào)用或者中斷時(shí)的現(xiàn)場(chǎng)。user_mode()根據(jù)regs中的cpsr寄存器來(lái)判斷是中斷現(xiàn)場(chǎng)環(huán)境還是用戶(hù)態(tài)環(huán)境。如果不是用戶(hù)態(tài)環(huán)境,就不對(duì)信號(hào)進(jìn)行任何處理,直接從do_signal()函數(shù)返回。

          如果user_mode()函數(shù)發(fā)現(xiàn)regs的現(xiàn)場(chǎng)是內(nèi)核態(tài),那就意味著這不是一次系統(tǒng)調(diào)用的返回,也不是一次普通的中斷返回,而是一次嵌套中斷返回(或者在系統(tǒng)調(diào)用過(guò)程中發(fā)生了中斷)。此時(shí)大概的執(zhí)行路徑應(yīng)該是這樣的:假設(shè)進(jìn)場(chǎng)現(xiàn)在運(yùn)行在用戶(hù)態(tài),此時(shí)發(fā)生一次中斷,進(jìn)場(chǎng)進(jìn)入內(nèi)核態(tài)(此時(shí)user_mode(regs)返回1,意味著中斷現(xiàn)場(chǎng)是用戶(hù)態(tài)。),此后在中斷返回前,發(fā)生了一個(gè)更高優(yōu)先級(jí)的中斷,于是CPU開(kāi)始執(zhí)行高優(yōu)先級(jí)的處理函數(shù)(此時(shí)user_mode(regs)返回0,意味著中斷現(xiàn)場(chǎng)是在內(nèi)核態(tài))。當(dāng)高優(yōu)先級(jí)中斷處理結(jié)束后,在它返回時(shí),是不應(yīng)該處理信號(hào)的,因?yàn)樾盘?hào)的優(yōu)先級(jí)比中斷的優(yōu)先級(jí)低。在這種情況下,對(duì)信號(hào)的處理將會(huì)延遲到低優(yōu)先級(jí)中斷處理結(jié)束之后。相對(duì)于Windows內(nèi)核來(lái)說(shuō),盡管linux內(nèi)核中沒(méi)有一組顯式的操作函數(shù)來(lái)實(shí)現(xiàn)這一系列的優(yōu)先級(jí)管理方案,但是linux內(nèi)核和Windows內(nèi)核都使用了同樣的機(jī)制,優(yōu)先級(jí)關(guān)系為:高優(yōu)先級(jí)中斷->低優(yōu)先級(jí)中斷->軟中斷(類(lèi)似Windows內(nèi)中的DPC)->信號(hào)(類(lèi)似Windows內(nèi)核中的APC)->進(jìn)程運(yùn)行。

          如果user_mode(regs)返回1,接下來(lái)會(huì)執(zhí)行(中間略去一下和本文關(guān)系不大的代碼)get_signal_to_deliver(),這個(gè)函數(shù)從當(dāng)前進(jìn)程的信號(hào)隊(duì)列(保存Private Signal Queue和Shared Signal Queue)取出等待處理的信號(hào)(調(diào)用dequeue_signal()函數(shù)),然后根據(jù)信號(hào)定位到對(duì)應(yīng)的signal_struct結(jié)構(gòu),如果信號(hào)的處理函數(shù)sa_handler為SIG_IGN,就忽略該信號(hào),繼續(xù)取下一個(gè)信號(hào);如果信號(hào)的處理函數(shù)sa_handler為SIG_DFL,意味著按照信號(hào)默認(rèn)的處理方式對(duì)待就可以了(例如直接調(diào)用do_coredump()等)。

          如果get_signal_to_deliver()函數(shù)返回值大于0,說(shuō)明這個(gè)信號(hào)的處理函數(shù)是在用戶(hù)態(tài)空間(通過(guò)signal()和sigaction()等函數(shù)設(shè)置的自定義信號(hào)處理函數(shù)。),將調(diào)用handle_signal()函數(shù)進(jìn)行處理。handle_signal()函數(shù)的定義如下:

          [plain]view plaincopy
          print?
          1. /*
          2. *OK,wereinvokingahandler
          3. */
          4. staticvoid
          5. handle_signal(unsignedlongsig,structk_sigaction*ka,
          6. siginfo_t*info,sigset_t*oldset,
          7. structpt_regs*regs,intsyscall)
          8. {
          9. structthread_info*thread=current_thread_info();
          10. structtask_struct*tsk=current;
          11. intusig=sig;
          12. intret;
          13. /*
          14. *Ifwewerefromasystemcall,checkforsystemcallrestarting...
          15. */
          16. if(syscall){
          17. switch(regs->ARM_r0){
          18. case-ERESTART_RESTARTBLOCK:
          19. case-ERESTARTNOHAND:
          20. regs->ARM_r0=-EINTR;
          21. break;
          22. case-ERESTARTSYS:
          23. if(!(ka->sa.sa_flags&SA_RESTART)){
          24. regs->ARM_r0=-EINTR;
          25. break;
          26. }
          27. /*fallthrough*/
          28. case-ERESTARTNOINTR:
          29. restart_syscall(regs);
          30. }
          31. }
          32. /*
          33. *translatethesignal
          34. */
          35. if(usig<32&&thread->exec_domain&&thread->exec_domain->signal_invmap)
          36. usig=thread->exec_domain->signal_invmap[usig];
          37. /*
          38. *Setupthestackframe//設(shè)置棧幀
          39. */
          40. if(ka->sa.sa_flags&SA_SIGINFO)
          41. ret=setup_rt_frame(usig,ka,info,oldset,regs);
          42. else
          43. ret=setup_frame(usig,ka,oldset,regs);
          44. /*
          45. *Checkthattheresultingregistersareactuallysane.
          46. */
          47. ret|=!valid_user_regs(regs);
          48. /*
          49. *Blockthesignalifwewereunsuccessful.
          50. */
          51. if(ret!=0){
          52. spin_lock_irq(&tsk->sighand->siglock);
          53. sigorsets(&tsk->blocked,&tsk->blocked,
          54. &ka->sa.sa_mask);
          55. if(!(ka->sa.sa_flags&SA_NODEFER))
          56. sigaddset(&tsk->blocked,sig);
          57. recalc_sigpending();
          58. spin_unlock_irq(&tsk->sighand->siglock);
          59. }
          60. if(ret==0)
          61. return;
          62. force_sigsegv(sig,tsk);
          63. }
          在這樣情況下,進(jìn)程當(dāng)前處于內(nèi)核態(tài),而信號(hào)處理函數(shù)卻處于用戶(hù)態(tài),為此必須在進(jìn)程的用戶(hù)態(tài)構(gòu)造一個(gè)臨時(shí)的堆棧環(huán)境(因?yàn)檫M(jìn)程的信號(hào)處理函數(shù)在進(jìn)行函數(shù)調(diào)用以及使用局部變量時(shí)需要使用堆棧。),然后進(jìn)入用戶(hù)態(tài)執(zhí)行信號(hào)處理函數(shù),最后再返回內(nèi)核態(tài)繼續(xù)執(zhí)行。在這個(gè)過(guò)程中,有以下幾個(gè)問(wèn)題需要解決:

          1.臨時(shí)的用戶(hù)態(tài)堆棧在哪里呢?這個(gè)很好解決,因?yàn)榭梢灾苯邮褂眠M(jìn)程現(xiàn)有的用戶(hù)態(tài)堆棧,這里要保證的是:使用結(jié)束后這個(gè)堆棧必須和使用前是一模一樣的。

          2.臨時(shí)堆棧解決后,需要確定的是通過(guò)什么方法來(lái)保證返回到用戶(hù)態(tài)后,進(jìn)程執(zhí)行的是信號(hào)的處理函數(shù)。我們知道在進(jìn)入內(nèi)核態(tài)時(shí),內(nèi)核態(tài)堆棧中保存了一個(gè)中斷現(xiàn)場(chǎng),也就是一個(gè)pt_regs結(jié)構(gòu),中斷返回地址就保存在pt_regts中的pc中,因此我們這里只要把當(dāng)前進(jìn)程的pt_regs中pc設(shè)置為sa_handler,然后返回到用戶(hù)態(tài)就開(kāi)始從sa_handler處開(kāi)始執(zhí)行了。

          [plain]view plaincopy
          print?
          1. unsignedlonghandler=(unsignedlong)ka->sa.sa_handler;
          2. regs->ARM_pc=handler;

          3.當(dāng)信號(hào)的用戶(hù)態(tài)處理函數(shù)執(zhí)行結(jié)束時(shí),需要再次進(jìn)入內(nèi)核態(tài),還原用戶(hù)態(tài)堆棧,并且修改pt_regs中的pc,保證將來(lái)能夠按照正常的方式返回用戶(hù)態(tài)。我們知道進(jìn)程要主動(dòng)進(jìn)入內(nèi)核態(tài)只有通過(guò)系統(tǒng)調(diào)用,出發(fā)異常等方法,為此內(nèi)核專(zhuān)門(mén)提供了一個(gè)系統(tǒng)調(diào)用sys_sigreturn()(還有一個(gè)sys_rt_sigreturn()),但是如何調(diào)用sys_sigreturn()呢?強(qiáng)制安裝信號(hào)處理函數(shù)最后必須調(diào)用一個(gè)sigreturn()不是一個(gè)好辦法,因?yàn)椴涣私鈨?nèi)核的程序員會(huì)對(duì)這個(gè)限制感到不解,為此程序員常常忘記在它們的信號(hào)處理函數(shù)的末尾調(diào)用sigreturn(),如果真是這樣,arm-linux-gcc也檢測(cè)不出這個(gè)錯(cuò)誤。為此,內(nèi)核修改regs的ARM_lr值,:

          [plain]view plaincopy
          print?
          1. regs->ARM_lr=retcode;

          當(dāng)用戶(hù)態(tài)信號(hào)處理函數(shù)運(yùn)行結(jié)束時(shí),會(huì)從lr取出返回地址,因此內(nèi)核在構(gòu)建臨時(shí)regs時(shí),會(huì)把上面這段代碼的入口地址保存在lr,這樣當(dāng)信號(hào)處理完成后,就會(huì)順利的通過(guò)系統(tǒng)調(diào)用sys_sigreturn()進(jìn)入內(nèi)核。

          4.當(dāng)通過(guò)構(gòu)造的sys_sigreturn()返回到內(nèi)核態(tài)之后,內(nèi)核需要順利的返回到用戶(hù)態(tài)執(zhí)行原來(lái)的代碼(信號(hào)處理前應(yīng)該返回的用戶(hù)空間狀態(tài)),但是此時(shí)進(jìn)入內(nèi)核空間的pt_regs上下文是通過(guò)sys_sigreturn()構(gòu)造的,而最初的內(nèi)核堆棧中的pt_regs上下文在第一次返回用戶(hù)空間執(zhí)行信號(hào)處理函數(shù)時(shí),就已經(jīng)被“銷(xiāo)毀”了(內(nèi)核態(tài)堆棧的pt_regs上下文在中斷返回后就不復(fù)存在了)。而現(xiàn)在必須通過(guò)最初的pt_regs上下文返回用戶(hù)態(tài),為此,在構(gòu)建臨時(shí)堆棧環(huán)境時(shí),內(nèi)核會(huì)把最初的pt_regs上下文備份到臨時(shí)堆棧中(位于用戶(hù)態(tài)堆棧),當(dāng)通過(guò)系統(tǒng)調(diào)用sys_sigreturn()再次進(jìn)入內(nèi)核時(shí),內(nèi)核從用戶(hù)態(tài)空間還原出原始的pt_regs。最后正常返回。

          通過(guò)上面的討論,我們知道在這個(gè)迂回的處理過(guò)程中,關(guān)鍵在于用戶(hù)態(tài)的臨時(shí)堆棧環(huán)境的建立,這是一個(gè)sigframe結(jié)構(gòu):

          [plain]view plaincopy
          print?
          1. /*
          2. *Doasignalreturn;undothesignalstack.Thesearealignedto64-bit.
          3. */
          4. structsigframe{
          5. structsigcontextsc;//保存一組寄存器上下文
          6. unsignedlongextramask[_NSIG_WORDS-1];
          7. unsignedlongretcode;//保存返回地址
          8. structaux_sigframeaux__attribute__((aligned(8)));
          9. };
          10. structrt_sigframe{
          11. structsiginfo__user*pinfo;
          12. void__user*puc;
          13. structsiginfoinfo;
          14. structucontextuc;
          15. unsignedlongretcode;
          16. structaux_sigframeaux__attribute__((aligned(8)));
          17. };
          其中的sigcontext的作用類(lèi)似于pt_regs用于保存相關(guān)寄存器上下文,原始的pt_regs的相關(guān)信息就備份在這里。而整個(gè)sigframe結(jié)構(gòu)是通過(guò)get_sigframe()函數(shù)在進(jìn)程用戶(hù)態(tài)空間分配的,get_sigframe()定義如下:

          [plain]view plaincopy
          print?
          1. staticinlinevoid__user*
          2. get_sigframe(structk_sigaction*ka,structpt_regs*regs,intframesize)
          3. {
          4. unsignedlongsp=regs->ARM_sp;
          5. void__user*frame;
          6. /*
          7. *ThisistheX/Opensanctionedsignalstackswitching.
          8. */
          9. if((ka->sa.sa_flags&SA_ONSTACK)&&!sas_ss_flags(sp))
          10. sp=current->sas_ss_sp+current->sas_ss_size;
          11. /*
          12. *ATPCSB01mandates8-bytealignment
          13. */
          14. frame=(void__user*)((sp-framesize)&~7);
          15. /*
          16. *Checkthatwecanactuallywritetothesignalframe.
          17. */
          18. if(!access_ok(VERIFY_WRITE,frame,framesize))
          19. frame=NULL;
          20. returnframe;
          21. }
          get_sigframe()通過(guò)用戶(hù)態(tài)空間堆棧的sp-sizeof(struct sigframe)在用戶(hù)態(tài)堆棧的頂部分配了一篇存儲(chǔ)空間,將來(lái)使用完成后,再通過(guò)sp+sizeof(struct sigframe)還原。

          通過(guò)上面的討論,我們?cè)倩氐絛o_signal()中來(lái),如果有用戶(hù)態(tài)的信號(hào)處理函數(shù),do_signal()會(huì)調(diào)用handle_signal(),handle_signal()將調(diào)用setup_frame()或者setup_rt_frame()來(lái)完成實(shí)際的工作,這里我們以setup_frame()為例進(jìn)行進(jìn)一步討論。

          [plain]view plaincopy
          print?
          1. staticint
          2. setup_frame(intusig,structk_sigaction*ka,sigset_t*set,structpt_regs*regs)
          3. {
          4. //在用戶(hù)態(tài)堆棧上分配一個(gè)sigframe結(jié)構(gòu)
          5. structsigframe__user*frame=get_sigframe(ka,regs,sizeof(*frame));
          6. interr=0;
          7. if(!frame)
          8. return1;
          9. //把相關(guān)信息從內(nèi)核態(tài)備份到用戶(hù)態(tài)堆棧的sigframe結(jié)構(gòu)中
          10. err|=setup_sigcontext(&frame->sc,&frame->aux,regs,set->sig[0]);
          11. if(_NSIG_WORDS>1){
          12. err|=__copy_to_user(frame->extramask,&set->sig[1],
          13. sizeof(frame->extramask));
          14. }
          15. if(err==0)
          16. err=setup_return(regs,ka,&frame->retcode,frame,usig);
          17. returnerr;
          18. }
          setup_return()設(shè)置返回地址,其定義如下:

          [plain]view plaincopy
          print?
          1. staticint
          2. setup_return(structpt_regs*regs,structk_sigaction*ka,
          3. unsignedlong__user*rc,void__user*frame,intusig)
          4. {
          5. unsignedlonghandler=(unsignedlong)ka->sa.sa_handler;
          6. unsignedlongretcode;
          7. intthumb=0;
          8. unsignedlongcpsr=regs->ARM_cpsr&~PSR_f;
          9. /*
          10. *Maybeweneedtodelivera32-bitsignaltoa26-bittask.
          11. */
          12. if(ka->sa.sa_flags&SA_THIRTYTWO)
          13. cpsr=(cpsr&~MODE_MASK)|USR_MODE;
          14. #ifdefCONFIG_ARM_THUMB
          15. if(elf_hwcap&HWCAP_THUMB){
          16. /*
          17. *TheLSBofthehandlerdeterminesifweregoingto
          18. *beusingTHUMBorARMmodeforthissignalhandler.
          19. */
          20. thumb=handler&1;
          21. if(thumb)
          22. cpsr|=PSR_T_BIT;
          23. else
          24. cpsr&=~PSR_T_BIT;
          25. }
          26. #endif
          27. //這里的retcode就是保存手工構(gòu)造的sigreturn()代碼
          28. if(ka->sa.sa_flags&SA_RESTORER){
          29. retcode=(unsignedlong)ka->sa.sa_restorer;
          30. }else{
          31. unsignedintidx=thumb;
          32. if(ka->sa.sa_flags&SA_SIGINFO)
          33. idx+=2;
          34. if(__put_user(sigreturn_codes[idx],rc))
          35. return1;
          36. if(cpsr&MODE32_BIT){
          37. /*
          38. *32-bitcodecanusethenewhigh-page
          39. *signalreturncodesupport.
          40. */
          41. retcode=KERN_SIGRETURN_CODE+(idx<<2)+thumb;
          42. }else{
          43. /*
          44. *Ensurethattheinstructioncachesees
          45. *thereturncodewrittenontothestack.
          46. */
          47. flush_icache_range((unsignedlong)rc,
          48. (unsignedlong)(rc+1));
          49. retcode=((unsignedlong)rc)+thumb;
          50. }
          51. }
          52. regs->ARM_r0=usig;
          53. regs->ARM_sp=(unsignedlong)frame;//堆棧
          54. regs->ARM_lr=retcode;//返回地址,當(dāng)用戶(hù)態(tài)信號(hào)處理函數(shù)結(jié)束時(shí),就會(huì)把這個(gè)地址作為返回地址
          55. regs->ARM_pc=handler;//信號(hào)處理函數(shù)
          56. regs->ARM_cpsr=cpsr;
          57. return0;
          58. }

          當(dāng)setup_frame()返回后,一切準(zhǔn)備就緒,因此可以從內(nèi)核態(tài)返回了,這樣就順利過(guò)渡到用戶(hù)態(tài)的信號(hào)處理函數(shù)。當(dāng)這個(gè)函數(shù)處理結(jié)束后,會(huì)通過(guò)retcode再次進(jìn)入內(nèi)核態(tài),現(xiàn)在我們看看retcode是如何處理的,下面的代碼選自glibc(2.3.2):

          [plain]view plaincopy
          print?
          1. #include
          2. /*IfnoSA_RESTORERfunctionwasspecifiedbytheapplicationweuse
          3. oneofthese.Thisavoidstheneedforthekerneltosynthesiseareturn
          4. instructiononthestack,whichwouldinvolveexpensivecacheflushes.*/
          5. ENTRY(__default_sa_restorer)
          6. swiSYS_ify(sigreturn)
          7. #ifdef__NR_rt_sigreturn
          8. ENTRY(__default_rt_sa_restorer)
          9. swiSYS_ify(rt_sigreturn)
          10. #defineSYS_ify(syscall_name)(__NR_##syscall_name)

          下面具體看看sys_sigreturn()的定義:

          [plain]view plaincopy
          print?
          1. asmlinkageintsys_sigreturn(structpt_regs*regs)
          2. {
          3. structsigframe__user*frame;
          4. sigset_tset;
          5. /*Alwaysmakeanypendingrestartedsystemcallsreturn-EINTR*/
          6. current_thread_info()->restart_block.fn=do_no_restart_syscall;
          7. /*
          8. *Sincewestackedthesignalona64-bitboundary,
          9. *thenspshouldbewordalignedhere.Ifits
          10. *not,thentheuseristryingtomesswithus.
          11. */
          12. if(regs->ARM_sp&7)
          13. gotobadframe;
          14. frame=(structsigframe__user*)regs->ARM_sp;
          15. if(!access_ok(VERIFY_READ,frame,sizeof(*frame)))
          16. gotobadframe;
          17. if(__get_user(set.sig[0],&frame->sc.oldmask)
          18. ||(_NSIG_WORDS>1
          19. &&__copy_from_user(&set.sig[1],&frame->extramask,
          20. sizeof(frame->extramask))))
          21. gotobadframe;
          22. sigdelsetmask(&set,~_BLOCKABLE);
          23. spin_lock_irq(¤t->sighand->siglock);
          24. current->blocked=set;
          25. recalc_sigpending();
          26. spin_unlock_irq(¤tt->sighand->siglock);
          27. if(restore_sigcontext(regs,&frame->sc,&frame->aux))
          28. gotobadframe;
          29. /*SendSIGTRAPifweresingle-stepping*/
          30. if(current->ptrace&PT_SINGLESTEP){
          31. ptrace_cancel_bpt(current);
          32. send_sig(SIGTRAP,current,1);
          33. }
          34. returnregs->ARM_r0;
          35. badframe:
          36. force_sig(SIGSEGV,current);
          37. return0;
          38. }
          這個(gè)函數(shù)主要調(diào)用restore_sigcontext()根據(jù)用戶(hù)態(tài)態(tài)堆棧上的sigframe備份還原pt_regs。

          [plain]view plaincopy
          print?
          1. staticint
          2. restore_sigcontext(structpt_regs*regs,structsigcontext__user*sc,
          3. structaux_sigframe__user*aux)
          4. {
          5. interr=0;
          6. __get_user_error(regs->ARM_r0,&sc->arm_r0,err);
          7. __get_user_error(regs->ARM_r1,&sc->arm_r1,err);
          8. __get_user_error(regs->ARM_r2,&sc->arm_r2,err);
          9. __get_user_error(regs->ARM_r3,&sc->arm_r3,err);
          10. __get_user_error(regs->ARM_r4,&sc->arm_r4,err);
          11. __get_user_error(regs->ARM_r5,&sc->arm_r5,err);
          12. __get_user_error(regs->ARM_r6,&sc->arm_r6,err);
          13. __get_user_error(regs->ARM_r7,&sc->arm_r7,err);
          14. __get_user_error(regs->ARM_r8,&sc->arm_r8,err);
          15. __get_user_error(regs->ARM_r9,&sc->arm_r9,err);
          16. __get_user_error(regs->ARM_r10,&sc->arm_r10,err);
          17. __get_user_error(regs->ARM_fp,&sc->arm_fp,err);
          18. __get_user_error(regs->ARM_ip,&sc->arm_ip,err);
          19. __get_user_error(regs->ARM_sp,&sc->arm_sp,err);
          20. __get_user_error(regs->ARM_lr,&sc->arm_lr,err);
          21. __get_user_error(regs->ARM_pc,&sc->arm_pc,err);
          22. __get_user_error(regs->ARM_cpsr,&sc->arm_cpsr,err);
          23. err|=!valid_user_regs(regs);
          24. #ifdefCONFIG_IWMMXT
          25. if(err==0&&test_thread_flag(TIF_USING_IWMMXT))
          26. err|=restore_iwmmxt_context(&aux->iwmmxt);
          27. #endif
          28. #ifdefCONFIG_VFP
          29. //if(err==0)
          30. //err|=vfp_restore_state(&aux->vfp);
          31. #endif
          32. returnerr;
          33. }
          restore_sigcontext()很簡(jiǎn)單,當(dāng)它返回后,通過(guò)sys_sigreturn()在內(nèi)核態(tài)堆棧建立的pt_regs已經(jīng)變?yōu)檎{(diào)用信號(hào)處理函數(shù)之前的pt_regs。這樣,sys_sigreturn()返回用戶(hù)態(tài)時(shí),就順利地過(guò)渡到處理之前的狀態(tài)了。


          評(píng)論


          技術(shù)專(zhuān)區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();