在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

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

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

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

            CPU architecture:ARM920T

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

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

            當(dāng)進(jìn)程被調(diào)度時,會調(diào)用do_notify_resume()來處理信號隊列中的信號。信號處理主要就是調(diào)用sighand_struct結(jié)構(gòu)中對應(yīng)的信號處理函數(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)志后,接下來就調(diào)用do_signal()函數(shù),我們來看看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)場,必須為用戶模式,否則直接返回
            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),我們在后面的文章中會具體分析
            27. signr=get_signal_to_deliver(&info,&ka,regs,NULL);//取出等待處理的信號
            28. if(signr>0){
            29. handle_signal(signr,&ka,&info,oldset,regs,syscall);//處理信號
            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ù)時,進(jìn)程一定處于內(nèi)核空間,通常進(jìn)程只有通過中斷或者系統(tǒng)調(diào)用才能進(jìn)入內(nèi)核空間,regs保存著系統(tǒng)調(diào)用或者中斷時的現(xiàn)場。user_mode()根據(jù)regs中的cpsr寄存器來判斷是中斷現(xiàn)場環(huán)境還是用戶態(tài)環(huán)境。如果不是用戶態(tài)環(huán)境,就不對信號進(jìn)行任何處理,直接從do_signal()函數(shù)返回。

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

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

            如果get_signal_to_deliver()函數(shù)返回值大于0,說明這個信號的處理函數(shù)是在用戶態(tài)空間(通過signal()和sigaction()等函數(shù)設(shè)置的自定義信號處理函數(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),而信號處理函數(shù)卻處于用戶態(tài),為此必須在進(jìn)程的用戶態(tài)構(gòu)造一個臨時的堆棧環(huán)境(因為進(jìn)程的信號處理函數(shù)在進(jìn)行函數(shù)調(diào)用以及使用局部變量時需要使用堆棧。),然后進(jìn)入用戶態(tài)執(zhí)行信號處理函數(shù),最后再返回內(nèi)核態(tài)繼續(xù)執(zhí)行。在這個過程中,有以下幾個問題需要解決:

            1.臨時的用戶態(tài)堆棧在哪里呢?這個很好解決,因為可以直接使用進(jìn)程現(xiàn)有的用戶態(tài)堆棧,這里要保證的是:使用結(jié)束后這個堆棧必須和使用前是一模一樣的。

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

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

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

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

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

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

            通過上面的討論,我們知道在這個迂回的處理過程中,關(guān)鍵在于用戶態(tài)的臨時堆棧環(huán)境的建立,這是一個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的作用類似于pt_regs用于保存相關(guān)寄存器上下文,原始的pt_regs的相關(guān)信息就備份在這里。而整個sigframe結(jié)構(gòu)是通過get_sigframe()函數(shù)在進(jìn)程用戶態(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()通過用戶態(tài)空間堆棧的sp-sizeof(struct sigframe)在用戶態(tài)堆棧的頂部分配了一篇存儲空間,將來使用完成后,再通過sp+sizeof(struct sigframe)還原。

            通過上面的討論,我們再回到do_signal()中來,如果有用戶態(tài)的信號處理函數(shù),do_signal()會調(diào)用handle_signal(),handle_signal()將調(diào)用setup_frame()或者setup_rt_frame()來完成實際的工作,這里我們以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. //在用戶態(tài)堆棧上分配一個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)備份到用戶態(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)用戶態(tài)信號處理函數(shù)結(jié)束時,就會把這個地址作為返回地址
            55. regs->ARM_pc=handler;//信號處理函數(shù)
            56. regs->ARM_cpsr=cpsr;
            57. return0;
            58. }

            當(dāng)setup_frame()返回后,一切準(zhǔn)備就緒,因此可以從內(nèi)核態(tài)返回了,這樣就順利過渡到用戶態(tài)的信號處理函數(shù)。當(dāng)這個函數(shù)處理結(jié)束后,會通過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. }
            這個函數(shù)主要調(diào)用restore_sigcontext()根據(jù)用戶態(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()很簡單,當(dāng)它返回后,通過sys_sigreturn()在內(nèi)核態(tài)堆棧建立的pt_regs已經(jīng)變?yōu)檎{(diào)用信號處理函數(shù)之前的pt_regs。這樣,sys_sigreturn()返回用戶態(tài)時,就順利地過渡到處理之前的狀態(tài)了。


            評論


            技術(shù)專區(qū)

            關(guān)閉