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

发布者:脑电狂徒最新更新时间:2016-03-02 来源: eefocus关键字:linux内核  信号机制-  用户层  内核层 手机看文章 扫描二维码
随时随地手机看文章
Kernel version:2.6.14

CPU architecture:ARM920T

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


1.简介

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

2.signal()

signal()的函数原型如下:

 

[plain] view plain copy
 
 print?
  1. void (*signal(int signum, void (*handler)(int)))(int);   
在使用该调用的进程中加入以下头文件:
[plain] view plain copy
 
 print?
  1. #include    

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

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

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

[plain] view plain copy
 
 print?
  1. /*  
  2.  * For backwards compatibility.  Functionality superseded by sigaction.  
  3.  */  
  4. asmlinkage unsigned long  
  5. sys_signal(int sig, __sighandler_t handler)  
  6. {  
  7.     struct k_sigaction new_sa, old_sa;  
  8.     int ret;  
  9.   
  10.     new_sa.sa.sa_handler = handler;  
  11.     new_sa.sa.sa_flags = SA_ONESHOT | SA_NOMASK;  
  12.   
  13.     ret = do_sigaction(sig, &new_sa, &old_sa);  
  14.   
  15.     return ret ? ret : (unsigned long)old_sa.sa.sa_handler;  
  16. }  

__sighandler_t的定义如下:

 

[plain] view plain copy
 
 print?
  1. typedef void __signalfn_t(int);  
  2. typedef __signalfn_t __user *__sighandler_t;  

 

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

2.sigaction()

sigaction()的函数原型如下:

 

[plain] view plain copy
 
 print?
  1. sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);  
sigaction()对应的系统调用为do_sigaction(),下面我们具体讲解do_sigaction()函数,其定义如下:

2.1do_sigaction()

[plain] view plain copy
 
 print?
  1. int  
  2. do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact)  
  3. {  
  4.     struct k_sigaction *k;  
  5.   
  6.     if (!valid_signal(sig) || sig < 1 || (act && sig_kernel_only(sig)))  
  7.         return -EINVAL;  
  8.   
  9.     k = ¤tt->sighand->action[sig-1];  
  10.   
  11.     spin_lock_irq(¤tt->sighand->siglock);  
  12.     if (signal_pending(current)) {  
  13.         /*  
  14.          * If there might be a fatal signal pending on multiple  
  15.          * threads, make sure we take it before changing the action.  
  16.          */  
  17.         spin_unlock_irq(¤tt->sighand->siglock);  
  18.         return -ERESTARTNOINTR;  
  19.     }  
  20.   
  21.     if (oact)//把原来的k_sigaction保存到oact结构中,这里是对整个数据结构进行复制  
  22.         *oact = *k;  
  23.   
  24.     if (act) {  
  25.         /*  
  26.          * POSIX 3.3.1.3:  
  27.          *  "Setting a signal action to SIG_IGN for a signal that is  
  28.          *   pending shall cause the pending signal to be discarded,  
  29.          *   whether or not it is blocked."  
  30.          *  
  31.          *  "Setting a signal action to SIG_DFL for a signal that is  
  32.          *   pending and whose default action is to ignore the signal  
  33.          *   (for example, SIGCHLD), shall cause the pending signal to  
  34.          *   be discarded, whether or not it is blocked"  
  35.          */  
  36.         if (act->sa.sa_handler == SIG_IGN ||  
  37.             (act->sa.sa_handler == SIG_DFL &&  
  38.              sig_kernel_ignore(sig))) {  
  39.             /*  
  40.              * This is a fairly rare case, so we only take the  
  41.              * tasklist_lock once we're sure we'll need it.  
  42.              * Now we must do this little unlock and relock  
  43.              * dance to maintain the lock hierarchy.  
  44.              */  
  45.             struct task_struct *t = current;  
  46.             spin_unlock_irq(&t->sighand->siglock);  
  47.             read_lock(&tasklist_lock);  
  48.             spin_lock_irq(&t->sighand->siglock);  
  49.             *k = *act; //把新的k_sigaction结构复制到进程的sighand->action中  
  50.   
  51.             sigdelsetmask(&k->sa.sa_mask,  
  52.                       sigmask(SIGKILL) | sigmask(SIGSTOP));  
  53.             rm_from_queue(sigmask(sig), &t->signal->shared_pending);  
  54.             do {  
  55.                 rm_from_queue(sigmask(sig), &t->pending);  
  56.                 recalc_sigpending_tsk(t);  
  57.                 t = next_thread(t);  
  58.             } while (t != current);  
  59.             spin_unlock_irq(¤t->sighand->siglock);  
  60.             read_unlock(&tasklist_lock);  
  61.             return 0;  
  62.         }  
  63.   
  64.         *k = *act; //把新的k_sigaction结构复制到进程的sighand->action中  
  65.         sigdelsetmask(&k->sa.sa_mask,  
  66.                   sigmask(SIGKILL) | sigmask(SIGSTOP));  
  67.     }  
  68.   
  69.     spin_unlock_irq(¤tt->sighand->siglock);  
  70.     return 0;  
  71. }  

关键字:linux内核  信号机制-  用户层  内核层 引用地址:linux内核中的信号机制--从用户层到内核层

上一篇:控制linux动态链接库导出函数
下一篇:linux内核中的信号机制--信号处理

推荐阅读最新更新时间:2024-03-16 14:45

linux内核启动流程
arch/arm/kernel/head-armv.S 该文件是内核最先执行的一个文件,包括内核入口ENTRY(stext)到start_kernel间的初始化代码,主要作用是检查CPU ID, Architecture Type,初始化BSS等操作,并跳到start_kernel函数。在执行前,处理器应满足以下状态: r0 - should be 0 r1 - unique architecture number MMU - off I-cache - on or off D-cache off view plain copy print ? /* 部分源代码分析 */ /* 内核入口点
[单片机]
基于S3C2440的Linux内核移植和yaffs2文件系统制作--编译内核
1.3.4、编译内核 编译内核需要遵守以下步骤: 1、make dep make dep的意思就是说:如果你使用程序A(比如支持特殊设备),而A需用到B(比如B是A的一 个模块/子程序)。而你在做make config的时候将一个设备的驱动 由内核支持改为module,或取消支持,这将可能影响到B的一个参数的设置,需重新编译B,重新编译或连接A....如果程序数量非常多, 你是很难手工完全做好此工作的。make dep实际上读取配置过程生成的配置文件,来创建对应于配置的依赖关系树,从而决定哪些需要编译而那些不需要编译。所以,你要make dep。 2、make clean 清除一些以前留下的文件,比如以前编译生成的目标文
[单片机]
linux内核中的信号机制--信号机制的管理结构
Kernel version:2.6.14 CPU architecture:ARM920T Author:ce123(http://blog.csdn.net/ce123) 信号只是一个数字,数字为0-31表示不同的信号,如下表所示。 编号 信号名 默认动作 说明 1 SIGHUP 进程终止 终端断开连接 2 SIGINT 进程终止 用户在键盘上按下CTRL+C 3 SIGQUIT 进程意外结束(Dump)
[单片机]
基于斯道S3C2410的Linux内核编译
1。编译缘由 使用斯道的zImage文件,我自己编译的Mplayer不能使用,必须加--nosound选项才能播放视频。后来见一篇文章说是Linux内核音频驱动的问题,所以决定重新编译内核。 2。编译工具及资料 2。1内核版本:斯道S3C2410普及版2光盘自带的 2。1交叉编译器:cross-2.95.3.tar.bz2,可能是在ARM官方的ftp服务器上下的,我忘了。 3。编译过程 3。1拷贝cross-2.95.3.tar.bz2到/usr/local/arm/目录,并转到/usr/local/arm目录 sudo cp cross-2.95.3.tar.bz2 /usr/local/arm sudo cd /usr/
[单片机]
基于tiny4412的Linux内核移植(支持device tree)(三)
平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本:Linux-4.4.0 (支持device tree) u-boot版本:友善之臂自带的 U-Boot 2010.12 (为支持uImage启动,做了少许改动) busybox版本:busybox 1.25 交叉编译工具链: arm-none-linux-gnueabi-gcc (gcc version 4.8.3 20140320 (prerelease) (Sourcery CodeBench Lite 2014.05-29)) 注意 继续上文。 到目前为止,板子已经可以起来了,接下来就可以针对板子的情况移植驱动程序了。
[单片机]
armv8(aarch64)linux内核中flush_dcache_all函数详细分析
/* * __flush_dcache_all() * Flush the wholeD-cache. * Corrupted registers: x0-x7, x9-x11 */ ENTRY(__flush_dcache_all) //保证之前的访存指令的顺序 dsb sy //读cache level id register mrs x0, clidr_el1 // read clidr //取bits (Level of Coherency for the cache hierarchy.) //需要遵循cache一致性的ca
[单片机]
armv8(aarch64)<font color='red'>linux内核</font>中flush_dcache_all函数详细分析
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved