新聞中心

EEPW首頁 > 嵌入式系統(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 來源:網(wǎng)絡(luò) 收藏
Kernel version:2.6.14

CPU architecture:ARM920T

本文引用地址:http://m.butianyuan.cn/article/201611/320006.htm

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

當(dāng)進(jìn)程被調(diào)度時(shí),會(huì)調(diào)用do_notify_resume()來處理信號(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)志后,接下來就調(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),我們?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)程只有通過中斷或者系統(tǒng)調(diào)用才能進(jìn)入內(nèi)核空間,regs保存著系統(tǒng)調(diào)用或者中斷時(shí)的現(xiàn)場。user_mode()根據(jù)regs中的cpsr寄存器來判斷是中斷現(xiàn)場環(huán)境還是用戶態(tài)環(huán)境。如果不是用戶態(tài)環(huán)境,就不對(duì)信號(hào)進(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ā)生了中斷)。此時(shí)大概的執(zhí)行路徑應(yīng)該是這樣的:假設(shè)進(jìn)場現(xiàn)在運(yùn)行在用戶態(tài),此時(shí)發(fā)生一次中斷,進(jìn)場進(jìn)入內(nèi)核態(tài)(此時(shí)user_mode(regs)返回1,意味著中斷現(xiàn)場是用戶態(tài)。),此后在中斷返回前,發(fā)生了一個(gè)更高優(yōu)先級(jí)的中斷,于是CPU開始執(zhí)行高優(yōu)先級(jí)的處理函數(shù)(此時(shí)user_mode(regs)返回0,意味著中斷現(xiàn)場是在內(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)核來說,盡管linux內(nèi)核中沒有一組顯式的操作函數(shù)來實(shí)現(xiàn)這一系列的優(yōu)先級(jí)管理方案,但是linux內(nèi)核和Windows內(nèi)核都使用了同樣的機(jī)制,優(yōu)先級(jí)關(guān)系為:高優(yōu)先級(jí)中斷->低優(yōu)先級(jí)中斷->軟中斷(類似Windows內(nèi)中的DPC)->信號(hào)(類似Windows內(nèi)核中的APC)->進(jìn)程運(yùn)行。

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

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

2.臨時(shí)堆棧解決后,需要確定的是通過什么方法來保證返回到用戶態(tài)后,進(jìn)程執(zhí)行的是信號(hào)的處理函數(shù)。我們知道在進(jìn)入內(nèi)核態(tài)時(shí),內(nèi)核態(tài)堆棧中保存了一個(gè)中斷現(xiàn)場,也就是一個(gè)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)信號(hào)的用戶態(tài)處理函數(shù)執(zhí)行結(jié)束時(shí),需要再次進(jìn)入內(nèi)核態(tài),還原用戶態(tài)堆棧,并且修改pt_regs中的pc,保證將來能夠按照正常的方式返回用戶態(tài)。我們知道進(jìn)程要主動(dòng)進(jìn)入內(nèi)核態(tài)只有通過系統(tǒng)調(diào)用,出發(fā)異常等方法,為此內(nèi)核專門提供了一個(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)用戶態(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ì)順利的通過系統(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í)行原來的代碼(信號(hào)處理前應(yīng)該返回的用戶空間狀態(tài)),但是此時(shí)進(jìn)入內(nèi)核空間的pt_regs上下文是通過sys_sigreturn()構(gòu)造的,而最初的內(nèi)核堆棧中的pt_regs上下文在第一次返回用戶空間執(zhí)行信號(hào)處理函數(shù)時(shí),就已經(jīng)被“銷毀”了(內(nèi)核態(tài)堆棧的pt_regs上下文在中斷返回后就不復(fù)存在了)。而現(xiàn)在必須通過最初的pt_regs上下文返回用戶態(tài),為此,在構(gòu)建臨時(shí)堆棧環(huán)境時(shí),內(nèi)核會(huì)把最初的pt_regs上下文備份到臨時(shí)堆棧中(位于用戶態(tài)堆棧),當(dāng)通過系統(tǒng)調(diào)用sys_sigreturn()再次進(jìn)入內(nèi)核時(shí),內(nèi)核從用戶態(tài)空間還原出原始的pt_regs。最后正常返回。

通過上面的討論,我們知道在這個(gè)迂回的處理過程中,關(guān)鍵在于用戶態(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的作用類似于pt_regs用于保存相關(guān)寄存器上下文,原始的pt_regs的相關(guān)信息就備份在這里。而整個(gè)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)堆棧的頂部分配了一篇存儲(chǔ)空間,將來使用完成后,再通過sp+sizeof(struct sigframe)還原。

通過上面的討論,我們?cè)倩氐絛o_signal()中來,如果有用戶態(tài)的信號(hào)處理函數(shù),do_signal()會(huì)調(diào)用handle_signal(),handle_signal()將調(diào)用setup_frame()或者setup_rt_frame()來完成實(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. //在用戶態(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)備份到用戶態(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)信號(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)返回了,這樣就順利過渡到用戶態(tài)的信號(hào)處理函數(shù)。當(dāng)這個(gè)函數(shù)處理結(jié)束后,會(huì)通過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ù)用戶態(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)用信號(hào)處理函數(shù)之前的pt_regs。這樣,sys_sigreturn()返回用戶態(tài)時(shí),就順利地過渡到處理之前的狀態(tài)了。


評(píng)論


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

關(guān)閉