微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > linux内核中的信号机制--从用户层到内核层

linux内核中的信号机制--从用户层到内核层

时间:11-22 来源:互联网 点击:
Kernel version:2.6.14

CPU architecture:ARM920T

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


1.简介

如果进程要处理某一信号,那么要在进程中注册该信号。注册信号主要用来确定信号值及进程针对该信号值的动作之间的映射关系,即进程将要处理哪个进程和该信号被传递给进程时,将执行何种操作。主要有两个函数实现信号的注册:signal()和sigaction()。

2.signal()

signal()的函数原型如下:

[plain]view plaincopyprint?

  1. void(*signal(intsignum,void(*handler)(int)))(int);

在使用该调用的进程中加入以下头文件:

[plain]view plaincopyprint?

  1. #include

上述声明格式比较复杂,如果不清楚如何使用,也可以通过下面这种类型定义的格式来使用(POSIX的定义):

[plain]view plaincopyprint?

  1. typedefvoid(*sighandler_t)(int);
  2. sighandler_tsignal(intsignum,sighandler_thandler);

但这种格式在不同的系统中有不同的类型定义,所以要使用这种格式,最好还是参考一下手册。在调用中,参数signum指出要设置处理方法的信号。第二个参数handler是一个处理函数,或者是
  • SIG_IGN:忽略参数signum所指的信号。
  • SIG_DFL:恢复参数signum所指信号的处理方法为默认值。
传递给信号处理例程的整数参数是信号值,这样可以使得一个信号处理例程处理多个信号。系统调用signal()返回值是指定信号signum前一次的处理例程或者错误时返回错误代码SIG_ERR。

signal()通过系统调用sys_signal()为一个指定的信号设置用户态处理函数。sys_signal()定义如下:

[plain]view plaincopyprint?

  1. /*
  2. *Forbackwardscompatibility.Functionalitysupersededbysigaction.
  3. */
  4. asmlinkageunsignedlong
  5. sys_signal(intsig,__sighandler_thandler)
  6. {
  7. structk_sigactionnew_sa,old_sa;
  8. intret;
  9. new_sa.sa.sa_handler=handler;
  10. new_sa.sa.sa_flags=SA_ONESHOT|SA_NOMASK;
  11. ret=do_sigaction(sig,&new_sa,&old_sa);
  12. returnret?ret:(unsignedlong)old_sa.sa.sa_handler;
  13. }

__sighandler_t的定义如下:

[plain]view plaincopyprint?

  1. typedefvoid__signalfn_t(int);
  2. typedef__signalfn_t__user*__sighandler_t;

信号由sys_signal()的第一个参数指定,信号处理函数的地址由第二个参数指定。sys_signal()根据这两个参数设置一个k_sigaction结构,然后调用do_sigaction(),该函数的定义我们会在后面具体讲解。

2.sigaction()

sigaction()的函数原型如下:

[plain]view plaincopyprint?

  1. sigaction(intsignum,conststructsigaction*act,structsigaction*oldact);

sigaction()对应的系统调用为do_sigaction(),下面我们具体讲解do_sigaction()函数,其定义如下:

2.1do_sigaction()

[plain]view plaincopyprint?

  1. int
  2. do_sigaction(intsig,conststructk_sigaction*act,structk_sigaction*oact)
  3. {
  4. structk_sigaction*k;
  5. if(!valid_signal(sig)||sig<1||(act&&sig_kernel_only(sig)))
  6. return-EINVAL;
  7. k=¤tt->sighand->action[sig-1];
  8. spin_lock_irq(¤tt->sighand->siglock);
  9. if(signal_pending(current)){
  10. /*
  11. *Iftheremightbeafatalsignalpendingonmultiple
  12. *threads,makesurewetakeitbeforechangingtheaction.
  13. */
  14. spin_unlock_irq(¤tt->sighand->siglock);
  15. return-ERESTARTNOINTR;
  16. }
  17. if(oact)//把原来的k_sigaction保存到oact结构中,这里是对整个数据结构进行复制
  18. *oact=*k;
  19. if(act){
  20. /*
  21. *POSIX3.3.1.3:
  22. *"SettingasignalactiontoSIG_IGNforasignalthatis
  23. *pendingshallcausethependingsignaltobediscarded,
  24. *whetherornotitisblocked."
  25. *
  26. *"SettingasignalactiontoSIG_DFLforasignalthatis
  27. *pendingandwhosedefaultactionistoignorethesignal
  28. *(forexample,SIGCHLD),shallcausethependingsignalto
  29. *bediscarded,whetherornotitisblocked"
  30. */
  31. if(act->sa.sa_handler==SIG_IGN||
  32. (act->sa.sa_handler==SIG_DFL&&
  33. sig_kernel_ignore(sig))){
  34. /*
  35. *Thisisafairlyrarecase,soweonlytakethe
  36. *tasklist_lockonceweresurewellneedit.
  37. *Nowwemustdothislittleunlockandrelock
  38. *dancetomaintainthelockhierarchy.
  39. */
  40. structtask_struct*t=current;
  41. spin_unlock_irq(&t->sighand->siglock);
  42. read_lock(&tasklist_lock);
  43. spin_lock_irq(&t->sighand->siglock);
  44. *k=*act;//把新的k_sigaction结构复制到进程的sighand->action中
  45. sigdelsetmask(&k->sa.sa_mask,
  46. sigmask(SIGKILL)|sigmask(SIGSTOP));
  47. rm_from_queue(sigmask(sig),&t->signal->shared_pending);
  48. do{
  49. rm_from_queue(sigmask(sig),&t->pending);
  50. recalc_sigpending_tsk(t);
  51. t=next_thre

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top