linux 中信号相关的一个结构体 struct sigaction 主要在sigaction信号安装和sigqueue信号发送时会用到
该结构位于/usr/include/bits/sigaction.h
在里面可以找到该结构的描述 {我现在实现的系统是as 4 内核版本 2.6.9-5.EL}
/* Structure describing the action to be taken when a signal arrives. */
struct sigaction
{
/* Signal handler. */
#ifdef __USE_POSIX199309
union
{
/* Used if SA_SIGINFO is not set. */
__sighandler_t sa_handler;
/* Used if SA_SIGINFO is set. */
void (*sa_sigaction) (int, siginfo_t *, void *);
}
__sigaction_handler;
# define sa_handler __sigaction_handler.sa_handler
# define sa_sigaction __sigaction_handler.sa_sigaction
#else
__sighandler_t sa_handler;
#endif
/* Additional set of signals to be blocked. */
__sigset_t sa_mask;
/* Special flags. */
int sa_flags;
/* Restore handler. */
void (*sa_restorer) (void);
};
在网上查了一些书料这个结构大概是这样的
其中,sa_restorer,已过时,POSIX不支持它,不应再被使用。
1、联合数据结构中的两个元素_sa_handler以及*_sa_sigaction指定信号关联函数,即用户指定的信号处理函数。除了可以是用户自定义的处理函数外,还可以为SIG_DFL(采用缺省的处理方式),也可以为SIG_IGN(忽略信号)。
2、由_sa_handler指定的处理函数只有一个参数,即信号值,所以信号不能传递除信号值之外的任何信息;由_sa_sigaction是指定的信号处理函数带有三个参数,是为实时信号而设的(当然同样支持非实时信号),它指定一个3参数信号处理函数。第一个参数为信号值,第三个参数没有使用(posix没有规范使用该参数的标准),第二个参数是指向siginfo_t结构的指针,结构中包含信号携带的数据值,参数所指向的结构如下:
在/usr/include/bits/siginfo.h中是这样定义的
typedef struct siginfo
{
int si_signo; /* Signal number. */
int si_errno; /* If non-zero, an errno value associated with
this signal, as defined in <errno.h>. */
int si_code; /* Signal code. */
union
{
int _pad[__SI_PAD_SIZE];
/* kill(). */
struct
{
__pid_t si_pid; /* Sending process ID. */
__uid_t si_uid; /* Real user ID of sending process. */
} _kill;
/* POSIX.1b timers. */
struct
{
int si_tid; /* Timer ID. */
int si_overrun; /* Overrun count. */
sigval_t si_sigval; /* Signal value. */
} _timer;
/* POSIX.1b signals. */
struct
{
__pid_t si_pid; /* Sending process ID. */
__uid_t si_uid; /* Real user ID of sending process. */
sigval_t si_sigval; /* Signal value. */
} _rt;
/* SIGCHLD. */
struct
{
__pid_t si_pid; /* Which child. */
__uid_t si_uid; /* Real user ID of sending process. */
int si_status; /* Exit value or signal. */
__clock_t si_utime;
__clock_t si_stime;
} _sigchld;
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS. */
struct
{
void *si_addr; /* Faulting insn/memory ref. */
} _sigfault;
/* SIGPOLL. */
struct
{
long int si_band; /* Band event for SIGPOLL. */
int si_fd;
} _sigpoll;
} _sifields;
} siginfo_t;
是不是太复杂了,在网上有一个简洁版我搬过来用一下
siginfo_t {
int si_signo; /* 信号值,对所有信号有意义*/
int si_errno; /* errno值,对所有信号有意义*/
int si_code; /* 信号产生的原因,对所有信号有意义*/
union{ /* 联合数据结构,不同成员适应不同信号 */
//确保分配足够大的存储空间
int _pad[SI_PAD_SIZE];
//对SIGKILL有意义的结构
struct{
...
}...
... ...
... ...
//对SIGILL, SIGFPE, SIGSEGV, SIGBUS有意义的结构
struct{
...
}...
... ...
}
}
3、sa_mask指定在信号处理程序执行过程中,哪些信号应当被阻塞。缺省情况下当前信号本身被阻塞,防止信号的嵌套发送,除非指定SA_NODEFER或者SA_NOMASK标志位。
注:请注意sa_mask指定的信号阻塞的前提条件,是在由sigaction()安装信号的处理函数执行过程中由sa_mask指定的信号才被阻塞。
4、sa_flags中包含了许多标志位,包括刚刚提到的SA_NODEFER及SA_NOMASK标志位。另一个比较重要的标志位是SA_SIGINFO,当设定了该标志位时,表示信号附带的参数可以被传递到信号处理函数中,因此,应该为sigaction结构中的sa_sigaction指定处理函数,而不应该为sa_handler指定信号处理函数,否则,设置该标志变得毫无意义。即使为sa_sigaction指定了信号处理函数,如果不设置SA_SIGINFO,信号处理函数同样不能得到信号传递过来的数据,在信号处理函数中对这些信息的访问都将导致段错误(Segmentation fault)。
注:很多文献在阐述该标志位时都认为,如果设置了该标志位,就必须定义三参数信号处理函数。实际不是这样的,验证方法很简单:自己实现一个单一参数信号处理函数,并在程序中设置该标志位,可以察看程序的运行结果。实际上,可以把该标志位看成信号是否传递参数的开关,如果设置该位,则传递参数;否则,不传递参数。
结构说的也差不多了,其实在我看到这些东西的时候给弄晕了好几回,简单的说几句就是
如果要在某信号产生时触发某些动作我们就可以安装信号
signal 用于安装不可靠信号 linux现在是用sigaction实现的
sigaction 用于安装可靠信号 当然他也可以安装不可靠信号 并且可以附带更多的信息
signal安装信号时只需传入2个参数 一个是信号的值 一个是信号发生时触发的函数,该函数接受一个整数
sigaction 安装时有3个参数 第一个参数是信号的值,第二个是sigaction结构 这个结构说明了信号发生时调用的函数和其它的一些信息,主要的成员是 sa_handler 指定的触发函数只带一个参数即信号的值 这和signal调用没什么区别,sa_sigaction指定的触发函数带有3个参数 第一个参数是信号的值,第二个参数是包函附加信息的结构siginfo,第三个参数为空 如果要传递附加信息给触发函数那么必须将传给sigaction的第二个参数sigaction结构的sa_flag设为SA_SIGINFO
上面说了那么多结构体和复杂的很的siginfo,其实siginfo我们在实际应用中并不需要去初始化他或者做什么,只是在信号触发时我们可以从这个结构体中提取一些信息
说了这么多我们可以小试牛刀了
自己写一个程序
[root@localhost clang]# cat f4.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
void test(int n,struct siginfo *siginfo,void *myact)
{
printf("signal number:%d\n",n);/** 打印出信号值 **/
printf("siginfo signo:%d\n",siginfo->si_signo); /** siginfo结构里保存的信号值 **/
printf("siginfo errno:%d\n",siginfo->si_errno); /** 打印出错误代码 **/
printf("siginfo code:%d\n",siginfo->si_code); /** 打印出出错原因 **/
}
int main(void)
{
/** install signal use sigaction **/
struct sigaction act;
sigemptyset(&act.sa_mask); /** 清空阻塞信号 **/
act.sa_flags=SA_SIGINFO; /** 设置SA_SIGINFO 表示传递附加信息到触发函数 **/
act.sa_sigaction=test;
if(sigaction(SIGINT,&act,NULL) < 0)
{
printf("install signal error\n");
}
while(1)
{
sleep(1);
printf("wait for the signal\n");
}
}
[root@localhost clang]#
[root@localhost clang]# ./test
wait for the signal
wait for the signal
wait for the signal
wait for the signal
signal number:2
siginfo signo:2
siginfo errno:0
siginfo code:128
wait for the signal
wait for the signal
wait for the signal
signal number:2
siginfo signo:2
siginfo errno:0
siginfo code:128
wait for the signal
[2]+ Stopped ./test
[root@localhost clang]# kill %1
[1]- Stopped vim f4.c
[root@localhost clang]#
可以看到当按下CTRL+C结束程序时信号将触发执行test函数
该结构位于/usr/include/bits/sigaction.h
在里面可以找到该结构的描述 {我现在实现的系统是as 4 内核版本 2.6.9-5.EL}
/* Structure describing the action to be taken when a signal arrives. */
struct sigaction
{
/* Signal handler. */
#ifdef __USE_POSIX199309
union
{
/* Used if SA_SIGINFO is not set. */
__sighandler_t sa_handler;
/* Used if SA_SIGINFO is set. */
void (*sa_sigaction) (int, siginfo_t *, void *);
}
__sigaction_handler;
# define sa_handler __sigaction_handler.sa_handler
# define sa_sigaction __sigaction_handler.sa_sigaction
#else
__sighandler_t sa_handler;
#endif
/* Additional set of signals to be blocked. */
__sigset_t sa_mask;
/* Special flags. */
int sa_flags;
/* Restore handler. */
void (*sa_restorer) (void);
};
在网上查了一些书料这个结构大概是这样的
其中,sa_restorer,已过时,POSIX不支持它,不应再被使用。
1、联合数据结构中的两个元素_sa_handler以及*_sa_sigaction指定信号关联函数,即用户指定的信号处理函数。除了可以是用户自定义的处理函数外,还可以为SIG_DFL(采用缺省的处理方式),也可以为SIG_IGN(忽略信号)。
2、由_sa_handler指定的处理函数只有一个参数,即信号值,所以信号不能传递除信号值之外的任何信息;由_sa_sigaction是指定的信号处理函数带有三个参数,是为实时信号而设的(当然同样支持非实时信号),它指定一个3参数信号处理函数。第一个参数为信号值,第三个参数没有使用(posix没有规范使用该参数的标准),第二个参数是指向siginfo_t结构的指针,结构中包含信号携带的数据值,参数所指向的结构如下:
在/usr/include/bits/siginfo.h中是这样定义的
typedef struct siginfo
{
int si_signo; /* Signal number. */
int si_errno; /* If non-zero, an errno value associated with
this signal, as defined in <errno.h>. */
int si_code; /* Signal code. */
union
{
int _pad[__SI_PAD_SIZE];
/* kill(). */
struct
{
__pid_t si_pid; /* Sending process ID. */
__uid_t si_uid; /* Real user ID of sending process. */
} _kill;
/* POSIX.1b timers. */
struct
{
int si_tid; /* Timer ID. */
int si_overrun; /* Overrun count. */
sigval_t si_sigval; /* Signal value. */
} _timer;
/* POSIX.1b signals. */
struct
{
__pid_t si_pid; /* Sending process ID. */
__uid_t si_uid; /* Real user ID of sending process. */
sigval_t si_sigval; /* Signal value. */
} _rt;
/* SIGCHLD. */
struct
{
__pid_t si_pid; /* Which child. */
__uid_t si_uid; /* Real user ID of sending process. */
int si_status; /* Exit value or signal. */
__clock_t si_utime;
__clock_t si_stime;
} _sigchld;
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS. */
struct
{
void *si_addr; /* Faulting insn/memory ref. */
} _sigfault;
/* SIGPOLL. */
struct
{
long int si_band; /* Band event for SIGPOLL. */
int si_fd;
} _sigpoll;
} _sifields;
} siginfo_t;
是不是太复杂了,在网上有一个简洁版我搬过来用一下
siginfo_t {
int si_signo; /* 信号值,对所有信号有意义*/
int si_errno; /* errno值,对所有信号有意义*/
int si_code; /* 信号产生的原因,对所有信号有意义*/
union{ /* 联合数据结构,不同成员适应不同信号 */
//确保分配足够大的存储空间
int _pad[SI_PAD_SIZE];
//对SIGKILL有意义的结构
struct{
...
}...
... ...
... ...
//对SIGILL, SIGFPE, SIGSEGV, SIGBUS有意义的结构
struct{
...
}...
... ...
}
}
3、sa_mask指定在信号处理程序执行过程中,哪些信号应当被阻塞。缺省情况下当前信号本身被阻塞,防止信号的嵌套发送,除非指定SA_NODEFER或者SA_NOMASK标志位。
注:请注意sa_mask指定的信号阻塞的前提条件,是在由sigaction()安装信号的处理函数执行过程中由sa_mask指定的信号才被阻塞。
4、sa_flags中包含了许多标志位,包括刚刚提到的SA_NODEFER及SA_NOMASK标志位。另一个比较重要的标志位是SA_SIGINFO,当设定了该标志位时,表示信号附带的参数可以被传递到信号处理函数中,因此,应该为sigaction结构中的sa_sigaction指定处理函数,而不应该为sa_handler指定信号处理函数,否则,设置该标志变得毫无意义。即使为sa_sigaction指定了信号处理函数,如果不设置SA_SIGINFO,信号处理函数同样不能得到信号传递过来的数据,在信号处理函数中对这些信息的访问都将导致段错误(Segmentation fault)。
注:很多文献在阐述该标志位时都认为,如果设置了该标志位,就必须定义三参数信号处理函数。实际不是这样的,验证方法很简单:自己实现一个单一参数信号处理函数,并在程序中设置该标志位,可以察看程序的运行结果。实际上,可以把该标志位看成信号是否传递参数的开关,如果设置该位,则传递参数;否则,不传递参数。
结构说的也差不多了,其实在我看到这些东西的时候给弄晕了好几回,简单的说几句就是
如果要在某信号产生时触发某些动作我们就可以安装信号
signal 用于安装不可靠信号 linux现在是用sigaction实现的
sigaction 用于安装可靠信号 当然他也可以安装不可靠信号 并且可以附带更多的信息
signal安装信号时只需传入2个参数 一个是信号的值 一个是信号发生时触发的函数,该函数接受一个整数
sigaction 安装时有3个参数 第一个参数是信号的值,第二个是sigaction结构 这个结构说明了信号发生时调用的函数和其它的一些信息,主要的成员是 sa_handler 指定的触发函数只带一个参数即信号的值 这和signal调用没什么区别,sa_sigaction指定的触发函数带有3个参数 第一个参数是信号的值,第二个参数是包函附加信息的结构siginfo,第三个参数为空 如果要传递附加信息给触发函数那么必须将传给sigaction的第二个参数sigaction结构的sa_flag设为SA_SIGINFO
上面说了那么多结构体和复杂的很的siginfo,其实siginfo我们在实际应用中并不需要去初始化他或者做什么,只是在信号触发时我们可以从这个结构体中提取一些信息
说了这么多我们可以小试牛刀了
自己写一个程序
[root@localhost clang]# cat f4.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
void test(int n,struct siginfo *siginfo,void *myact)
{
printf("signal number:%d\n",n);/** 打印出信号值 **/
printf("siginfo signo:%d\n",siginfo->si_signo); /** siginfo结构里保存的信号值 **/
printf("siginfo errno:%d\n",siginfo->si_errno); /** 打印出错误代码 **/
printf("siginfo code:%d\n",siginfo->si_code); /** 打印出出错原因 **/
}
int main(void)
{
/** install signal use sigaction **/
struct sigaction act;
sigemptyset(&act.sa_mask); /** 清空阻塞信号 **/
act.sa_flags=SA_SIGINFO; /** 设置SA_SIGINFO 表示传递附加信息到触发函数 **/
act.sa_sigaction=test;
if(sigaction(SIGINT,&act,NULL) < 0)
{
printf("install signal error\n");
}
while(1)
{
sleep(1);
printf("wait for the signal\n");
}
}
[root@localhost clang]#
[root@localhost clang]# ./test
wait for the signal
wait for the signal
wait for the signal
wait for the signal
signal number:2
siginfo signo:2
siginfo errno:0
siginfo code:128
wait for the signal
wait for the signal
wait for the signal
signal number:2
siginfo signo:2
siginfo errno:0
siginfo code:128
wait for the signal
[2]+ Stopped ./test
[root@localhost clang]# kill %1
[1]- Stopped vim f4.c
[root@localhost clang]#
可以看到当按下CTRL+C结束程序时信号将触发执行test函数
发表评论
-
crond需要重启么?
2011-06-11 12:20 1222今天一同事说把A机器的/var/spool/cron/admi ... -
GDB信号的处理和启动配置文件(转载)
2011-05-22 21:57 2203信号的处理 程序是和网络相关的,调试期间经常地收到SIGPIP ... -
asprintf
2011-05-08 21:49 2325sprintf() 的整个介面长的样子的是: int ... -
获取用户输入的问题(清除stdin)
2011-05-08 21:37 1906需求: 从终端获取用户输入的用户名和密码(有效 ... -
Linux下的UDP/TCP端口映射(netcat and socat)
2011-05-07 20:42 9664说起来有点土,事到如今 ... -
linux任务管理
2011-05-07 20:32 679disown是bash内部命令,nohup是外部命令 diso ... -
boost multi_index_container
2011-04-27 21:18 1524本章介绍的主题是multi_i ... -
变量相关命令(env,export,set,read, array, declare
2011-04-26 21:38 1001系统的预设参数文件:/ ... -
stl priority_queue
2011-04-26 21:20 601简单的使用示例。 view plaincopy to cli ... -
linux backlog
2011-04-25 15:13 1491在linux中,/proc/sys/net/core/so ... -
linux backlog
2011-04-25 15:13 730在linux中,/proc/sys/net/core/so ... -
stl hash_map
2011-04-23 19:57 749#include <cstdlib> #incl ... -
linux串口登陆
2011-04-23 09:31 1478在这个互连网高速发展的时代, 企业内网络设备的安全和运行稳定也 ... -
linux rename
2011-04-21 09:38 707Linux中rename命令的用法 刚学习linux的时候, ... -
stl heap
2011-04-17 10:01 767make_heap 原型: #include <a ... -
expand and upexpand
2011-04-09 13:33 707expand: NAME expand - co ... -
内核模块相关命令:lsmod,depmod,modprobe
2011-03-28 13:24 1108lsmod 功能:列出内核已载入模块的状态 用法:lsmod ... -
通过先unlink()后close()创建安全的临时文件
2011-03-15 14:26 883使用POSIX(Portable Operating Syst ... -
parted操作磁盘
2011-03-12 16:15 807除了fdisk命令,在linux下还有一个功能也非常强大的磁盘 ... -
linux写缓存调优
2011-03-11 09:34 2002我们在磁盘写操作持续 ...
相关推荐
VC线程信号量的使用举例源码,点击启动线程,可发现出现了什么。介绍线程方面的基础知识技巧。
摄影基础知识 一、摄影原理:透镜成像原理 透镜成像原理公式: 二、摄影机的基本结构 摄影机的基本结构 1. 镜头 图2-3 摄影机的镜头 2. 光圈 光圈:控制进入镜头的光量,调节镜头的使用面积,限制镜头边缘部分的使用...
前期主要利用P、V信号量来控制各进程间的同步于互斥关系,确保各进程有序正确的进行。然而,我们也知道,使用信号量和P、V操作在实现进程同步时,对共享资源的管理分散于各个进程中,进程能够直接对共享变量进行处理...
最近在学习python,发现了解线程信号量的基础知识,对深入理解python的线程会大有帮助。所以本文将给大家介绍Python3.X线程中信号量的使用方法,下面话不多说,来一起看看详细的介绍: 方法示例 线程中,信号量主要...
(2)不一致的估计量 (2)频率分辨率较差 (3)通过补零,它可以增加频率的观察点,但没有增加频率分辨率 (2) 位于染色体上,并在染色体上呈线性排列 (3)
2.2 P、V信号量 70 2.3 三态模型 71 2.4 死锁 72 2.5 进程资源图 73 2.6 文件管理 74 2.7 存储管理 75 3 程序语言基础 76 3.1 程序设计语言 76 3.2 程序编译 76 3.3 文法 76 3.4 程序控制结构 77 3.5 表达式 77 3.6 ...
最全最详细!请收下这份电路反馈基础知识秘 反馈,就是把放大电路的输出量的一部分或全部,通过反馈网络以一定的方式又引回到放大电路的输入回路中去,以影响电路的输入信号作用的过程。
主要介绍了PHP进程通信基础知识中的信号量与共享内存通信的相关资料,有需要的小伙伴可以查看下
设计与验证基础 脚本 笔面试题集 rtl_code 状态机设计 异步FIFO设计 亚稳态的世界 信号处理 同步FIFO设计 ...基础知识题集 多时钟处理 低功耗设计 存储单元与模块 verilog语法知识 FPGA内部结构 ...
有关于数字电路的基础知识:数制与码制 比如: 自然界存在各种各样的物理量,有以电的形式出现,有以声、光、磁、力等形式出现 模拟量:变化在时间或数值上是连续的物理量。 数字量:变化在时间上和数量上都是离散的...
基础知识 并发与并行 Java并发演进历史 Java并发模型 线程模型 存储模型 JVM同步原语 volatile CAS 线程安全 保护“共享数据” 低级并发工具 原子变量 锁(内部锁和显式锁) 线程安全容器...
本书在扼要复习信号检测与估计理论基础知识后,首先论述信号的统计检测理论和信号波形的检测,介绍了基于简单假设检验的确知信号最佳检测的概念、理论、技术和性能以及基于复合假设检验的随机参量信号的最佳检测问题...
第1章 计算机基础知识 计算机基础与C语言程序设计(第三版)第1章-计算机基础知识全文共98页,当前为第1页。 第1章 计算机基础知识 1.1 计算机系统与工作原理 1.2 数制与编码 1.3 PC的基本配置及性能指标 计算机基础与...
服务器基础知识介绍 目录 一、 服务器的基本概念 二、服务器关键部件介绍 三、服务器对接存储技术 四、服务器对接网络技术 一、服务器的基本概念 1.1 服务器是什么 1.2 服务器概述 1.3 服务器设备的物理结构 1.4 ...
9 (1) 计算机的硬件结构: ( 表示数据传送线, 表示控制信号线) 输入设备 存储器 输出设备 控制器 运算器 计算机基础知识和计算机基本操作全文共63页,当前为第9页。 10 (2) 计算机各部件的主要功能 1) 运算器...
qt的基础学习,包含信号量,控件的使用,内含大量的使用案例,c++学习可视化开发的一个选择,入门qt的最好选择
https://blog.csdn.net/weixin_51911075/article/details/128022926?spm=1001.2014.3001.5501此篇文章是描述Linux信号知识,有概念描述、举例例证、截图示意......信号是进程间通信的一种手段;是一种事件触发机制...
有鉴于此 安森美半导体的产品应用总监Bernie Weir先生近期专门撰写相关培训资料 为工程师们传授相关的设计基础知识 内容涉及LED驱动器的通用要求 电源拓扑结构 功率因数校正 电源转换能效和驱动器标准 以及可靠性和...
测量现实世界现象的许多传感器都以改变电阻的形式表现其输出:热敏电阻为温度敏感型电阻,...增加一个分压器并差分测量输出可以消除大失调量,请见图 2。 图2 增加第二个分压器并进行差分测量 该电路的输出电