- 浏览: 333879 次
- 性别:
- 来自: 福建福州
文章分类
最新评论
-
jw72jw:
最后这个是打表求值
LUA源码分析三:table分析(1) -
dyllove98:
"一些非常重要的问题,涉及面少。那这个时候,我更崇尚 ...
乱写:团队里的独裁和民主一点看法 -
jvmlover:
被踩10次了,什么思想感情啊。
LUA源码分析三:table分析(1) -
chenchenfly99:
chenchenfly99 写道
MMO游戏终极内测开服一周,问题记录 -
chenchenfly99:
...
MMO游戏终极内测开服一周,问题记录
本杂文主要是讲解了下信号和进程的关系。前面主要是一些man式的资料描述和书上一些例子的摘要。因为我想一篇记载性的东西多少得放点让人有点回忆性的代码和知识点。主要内容可从sigaction直接开始看。。。
正文
我觉得这是挺好理解的,就好比在系统这个大进程里运行许多派生的进程,为了协调这些派生出的子进程,就必然要使用一些手段来通知监视。而信号就是这样一种系统级别的全局变量的通知。想想在写程序中,多个函数协调一个全局函数的情形。。。
the signal is an event generated by the UNIX and Linux systems in response to some condition,upon receipt of which a process may in turn take some action.
函数
我想我需要如下系列的函数,修改本身的信号处理函数,对其他进程发送信号,
#include <signal.h>
void (*signal(int sig, void (*func)(int)))(int);
which
is the previous value of the function set up to handle this signal, or one of these two special values:
比如想捕捉SIGINT信号,但是我们又只想捕捉一次,就可以用到DFL信号来恢复之前的行为,可能会是这样
但要注意的是,It is no safe to call all function, such as printf, from within a signal handler.A useful technique is to use a signal handler to set flag and then check that flag from the main
pg and print a message if required.Toward the end of the chapter, you will find a list of calls that can safely be made inside signal handlers.
来点强壮的
X/Open规范的更新更健壮的接口
#include <signal.h>
int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
oact如果不为空,将把前次act的状态保存下来。
这个函数主要的是加入了信号集(sa_mask)这个功能。比如前面提到的,如果信号先发出而后调用pause(),则遗失掉这个信号。采用信号集他可以先收集或者说阻塞不传递给主进程,由主进程再来自主调用和处理。
对这个信号集有如下几种操作:
初始为空集,初始为所有已有的信号,增加新信号,删除指定信号
然后是一个批处理的函数
判断是否是当前信号集里的信号
int sigismember(sigset_t *set, int signo);
最后就是最重要的,对信号集里的信号进行操作,假设已经把信号收集到,主程序可以阻塞/非阻塞式的调用。(不过非阻塞的调用好象不能自动把收到的信号清除掉,阻塞式的就可以自动清除)。
If a signal is blocked by a process, it won’t be delivered, but will remain pending. A program can determine
which of its blocked signals are pending by calling the function sigpending.
#include <signal.h>
int sigpending(sigset_t *set);
A process can suspend execution until the delivery of one of a set of signals by calling sigsuspend. This
is a more general form of the pause function we met earlier.
#include <signal.h>
int sigsuspend(const sigset_t *sigmask);
sigaction Flags
The sa_flags field of the sigaction structure used in sigaction may contain the following values to
modify signal behavior:
通过以上的操作介绍,似乎已经很完美了。但是最大的问题来了,先了解几个概念:
不完全重入函数:即可能被其他信号中断触发EINTR
假设我们现在正在执行一个信号处理函数,突然发生一个中断,那么该信号函数将被打断。在一次情况下似乎没什么问题。但是假如连续性的被信号打断,而导致函数不断重启。就比如执行到一半退出,又执行,又退,又执行。。那么可能就有问题发生。有两个方法可以解决
1、根本方法,用完全重入函数。如下图所示英文版 P474
2、如果非不得以,那就不让信号来阻断信号函数的运行。可以用SA_RESTART标志把信号先放到屏蔽集的缓冲区里
操作如下,首先运行该程序,然后在另一个tty里发送一个kill命令(在第一个select未结束前),那么将进入信号处理函数ouch,接着在ouch的select运行之际,再次发送kill,因为select也不完全函数,将会被再次打断,而又一次进入信号。但是因为设置了SA_RESTART,ouch将不会被打断,而是执行完后,接着执行响应第二次的信号函数。
SA_NODEFER
和上面一样的操作,发送第二次KILL信号时,第一个信号函数马上中断(由于是select),又再次进入信号函数。这里加点东西打印可以更清楚些。
流程图
以上这两种实现,有个东西起了至关重要的作用。那就是进程的信号屏蔽字。原理流程大概是这样的,当向一个进程发送信号时,可根据是否被屏蔽掉而发送至进程信号屏蔽字集合中或者进程本身。对于后者,sigaction可直接捕捉到,而前者,可以看成是一个暂存的集合,可用sigpending来取得。通常的情况是,已经用了sigaction函数直接获取信号,如果再次触发信号会马上跳出当前正在执行的信号函数而再次执行信号函数。而SA_RESTART这个标志应该是将信号保存到被屏蔽的信号集合里等待下次取出后执行,保证了当前函数的运行。SA_NODEFER就不做这一操作,直接发送到进程,让sigaction继续马上捕捉。
整个走向可看下图,当然这里没有参考系统源码,必然存在着一定的疏忽
目前已知的对屏蔽集的操作有pending/suspend函数,SA_RESTART,SA_NODEFER标志操作。写到这里,把屏蔽集合集看成一个临时的信号存放缓冲区更形象点。
正文
我觉得这是挺好理解的,就好比在系统这个大进程里运行许多派生的进程,为了协调这些派生出的子进程,就必然要使用一些手段来通知监视。而信号就是这样一种系统级别的全局变量的通知。想想在写程序中,多个函数协调一个全局函数的情形。。。
the signal is an event generated by the UNIX and Linux systems in response to some condition,upon receipt of which a process may in turn take some action.
函数
我想我需要如下系列的函数,修改本身的信号处理函数,对其他进程发送信号,
#include <signal.h>
void (*signal(int sig, void (*func)(int)))(int);
which
is the previous value of the function set up to handle this signal, or one of these two special values:
SIG_IGN Ignore the signal. SIG_DFL Restore default behavior.
比如想捕捉SIGINT信号,但是我们又只想捕捉一次,就可以用到DFL信号来恢复之前的行为,可能会是这样
但要注意的是,It is no safe to call all function, such as printf, from within a signal handler.A useful technique is to use a signal handler to set flag and then check that flag from the main
pg and print a message if required.Toward the end of the chapter, you will find a list of calls that can safely be made inside signal handlers.
void ouch(int sig) { printf("OUCH ! - I got signal %d\n", sig); signal(SIGINT, SIG_DFL); } int main(int argc, char **argv) { signal(SIGINT, ouch); while(1) { printf("Hello World!\n"); sleep(1); } return 0; }
来点强壮的
X/Open规范的更新更健壮的接口
#include <signal.h>
int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
oact如果不为空,将把前次act的状态保存下来。
这个函数主要的是加入了信号集(sa_mask)这个功能。比如前面提到的,如果信号先发出而后调用pause(),则遗失掉这个信号。采用信号集他可以先收集或者说阻塞不传递给主进程,由主进程再来自主调用和处理。
void (*) (int) sa_handler /* function, SIG_DFL or SIG_IGN sigset_t sa_mask /* signals to block in sa_handler int sa_flags /* signal action modifiers,SA_RESETHAND,具有reset功能
对这个信号集有如下几种操作:
初始为空集,初始为所有已有的信号,增加新信号,删除指定信号
#include <signal.h> int sigaddset(sigset_t *set, int signo); int sigemptyset(sigset_t *set); int sigfillset(sigset_t *set); int sigdelset(sigset_t *set, int signo);
然后是一个批处理的函数
int sigprocmask(int how, const sigset_t *set, sigset_t *oset); SIG_BLOCK The signals in set are added to the signal mask. SIG_SETMASK The signal mask is set from set. SIG_UNBLOCK The signals in set are removed from the signal mask.
判断是否是当前信号集里的信号
int sigismember(sigset_t *set, int signo);
最后就是最重要的,对信号集里的信号进行操作,假设已经把信号收集到,主程序可以阻塞/非阻塞式的调用。(不过非阻塞的调用好象不能自动把收到的信号清除掉,阻塞式的就可以自动清除)。
If a signal is blocked by a process, it won’t be delivered, but will remain pending. A program can determine
which of its blocked signals are pending by calling the function sigpending.
#include <signal.h>
int sigpending(sigset_t *set);
A process can suspend execution until the delivery of one of a set of signals by calling sigsuspend. This
is a more general form of the pause function we met earlier.
#include <signal.h>
int sigsuspend(const sigset_t *sigmask);
sigaction Flags
The sa_flags field of the sigaction structure used in sigaction may contain the following values to
modify signal behavior:
SA_NOCLDSTOP Don’t generate SIGCHLD when child processes stop. SA_RESETHAND Reset signal action to SIG_DFL on receipt. SA_RESTART Restart interruptible functions rather than error with EINTR. SA_NODEFER Don’t add the signal to the signal mask when caught.
通过以上的操作介绍,似乎已经很完美了。但是最大的问题来了,先了解几个概念:
不完全重入函数:即可能被其他信号中断触发EINTR
假设我们现在正在执行一个信号处理函数,突然发生一个中断,那么该信号函数将被打断。在一次情况下似乎没什么问题。但是假如连续性的被信号打断,而导致函数不断重启。就比如执行到一半退出,又执行,又退,又执行。。那么可能就有问题发生。有两个方法可以解决
1、根本方法,用完全重入函数。如下图所示英文版 P474
2、如果非不得以,那就不让信号来阻断信号函数的运行。可以用SA_RESTART标志把信号先放到屏蔽集的缓冲区里
SA_RESTART(似乎默认也是这个行为) void ouch(int sig) { //.. select()//10秒 //.. } int main(int argc, char **argv) { struct sigaction act, act_g; act.sa_handler = ouch; act.sa_flags = SA_RESTART; //设置重启 sigemptyset(&act.sa_mask); sigaddset(&act.sa_mask, SIGTERM); if( -1==sigaction(SIGTERM, &act, 0)) //捕捉SIGTERM { perror("sigaction\n"); } select//10秒 }
操作如下,首先运行该程序,然后在另一个tty里发送一个kill命令(在第一个select未结束前),那么将进入信号处理函数ouch,接着在ouch的select运行之际,再次发送kill,因为select也不完全函数,将会被再次打断,而又一次进入信号。但是因为设置了SA_RESTART,ouch将不会被打断,而是执行完后,接着执行响应第二次的信号函数。
SA_NODEFER
和上面一样的操作,发送第二次KILL信号时,第一个信号函数马上中断(由于是select),又再次进入信号函数。这里加点东西打印可以更清楚些。
流程图
以上这两种实现,有个东西起了至关重要的作用。那就是进程的信号屏蔽字。原理流程大概是这样的,当向一个进程发送信号时,可根据是否被屏蔽掉而发送至进程信号屏蔽字集合中或者进程本身。对于后者,sigaction可直接捕捉到,而前者,可以看成是一个暂存的集合,可用sigpending来取得。通常的情况是,已经用了sigaction函数直接获取信号,如果再次触发信号会马上跳出当前正在执行的信号函数而再次执行信号函数。而SA_RESTART这个标志应该是将信号保存到被屏蔽的信号集合里等待下次取出后执行,保证了当前函数的运行。SA_NODEFER就不做这一操作,直接发送到进程,让sigaction继续马上捕捉。
整个走向可看下图,当然这里没有参考系统源码,必然存在着一定的疏忽
目前已知的对屏蔽集的操作有pending/suspend函数,SA_RESTART,SA_NODEFER标志操作。写到这里,把屏蔽集合集看成一个临时的信号存放缓冲区更形象点。
发表评论
-
linux内存分配slub的几个疑问
2011-01-13 08:21 1641对于SLUB不熟的同学可以 ... -
开源一个windows下的内存分配器slab,
2010-10-28 20:23 1378模仿linux内核下的slab而写。一些地址页面做了些新的工作 ... -
网络编程中缓冲带来的异步以及需要设置(windows)
2010-08-08 03:50 0此次的疑问主要来自IOCP下的程序编写。 WINDOWS下的 ... -
小议内存池、资源池
2010-08-02 21:08 2153比较简单的一篇文章。本来是有些地方没想明白,想分析一下。结果写 ... -
(00XX系列)抽抽Windows宽字符的棉絮(附日志文件源码)
2009-11-21 17:18 1239爷最近和可 ... -
(00XX系列)摸摸Windows的SEH
2009-11-16 23:13 1622节一:终止处理(Termination Handlers) 节 ... -
配置主机无线网络+虚拟机linux的上网
2009-09-05 11:04 4835环境如下: windows2003主机,虚拟机VM精简版,装有 ... -
碎片:linux vs windows, 内存/硬盘
2009-08-23 13:12 1642找了一堆资料,稍微整 ... -
分析《进程间通信》一书中的读/写锁策略
2008-08-27 17:00 3375以下代码和资料均学习自:《进程间通信》第8章读写锁 其中附件中 ... -
基础:systemV 信号 create send recv rmid
2008-07-26 17:30 1199/* @gcc version 3.2.2 200302 ... -
让您轻松理解execl函数系列 ^_^
2008-06-19 20:03 6842execl函数功能如下:启动一个可执行文件,并且对他进行传送参 ... -
[收集 转载]关于Linux下编写和编译程序的几个问题
2008-04-23 09:09 1858FROM http://www.fmm7.com/jsjc/w ... -
资料存放 linux命令收集和问题记录
2008-03-30 23:03 1360rm -rf name //递归删除 -
Linux基本目录用途
2008-03-24 10:19 1927/bin 该目录中存放Linux的常用命令,在有的版本中是一 ... -
在CentOS 4.4下安装gcc--RPM
2008-03-23 22:28 3358yum install gcc(需要的组件,即你也可以下载以下 ... -
资料存放 yum
2008-03-23 20:47 1067使用 yum 升级和 yum 使用 ... -
资料存放 tar
2008-03-23 20:46 1071tar命令 tar可以为文件和目录创建档案。利用tar,用户可 ... -
初学LINUX:架设一个 VSFTPD服务器系列
2008-03-09 01:33 1552实习的公司需要用到 LINUX,而自己也想深入这方面 公司用的 ... -
虚拟机中设置linux连接网络
2008-03-01 17:21 3790虚拟机:vmware Linux版本:CentOS(版本不会造 ... -
CentOS资料分类
2008-02-08 16:30 1733http://centos.ustc.edu.cn/CentO ...
相关推荐
sigaction.c 文件下载后直接编译运行,详情看博客
sigaction函数的功能是检查或修改与指定信号相关联的处理动作(可同时两种操作)
sigaction 函数原型定义如下: int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact) 这个系统调用的作用是改变进程接收到的指定信号的行动。 使用这个函数需要包含头文件#...
该程序是我写的博客“一起talk C栗子吧(v第八十六回:C语言实例--使用信号进行进程间通信三)”的配套程序,共享给大家使用
linux 下实现sleep详解及简单实例 sleep: 普通版本 1、基本设计思路: 1>注册SIGALRM信号的处理函数; 2>调用alarm(nsecs)设定闹钟; 3>调⽤pause等待,内核切换到别的进程运行; 4>nsecs秒之后,闹钟超时,内...
定义函数 int sigaction(int signum,const struct sigaction *act ,struct sigaction *oldact); 函数说明 sigaction()会依参数signum指定的信号编号来设置该信号的处理函数。参数signum可以指定SIGKILL和...
前言 慢系统调用,指的是可能永远无法返回,从而使进程永远... 如果信号处理函数是用sigaction注册的 默认情况下,系统调用不会自动重启,函数将返回失败,同时errno被置为EINTR 只有中断信号的SA_RESTART标志有效时
sigaction函数的具体介绍
对linux信号机制的详细阐述,包括signal,sigaction等函数的用法,并配以实例,通俗易懂,适合初学者阅读。。。
linux除了支持Unix早期信号语义函数signal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数);...
利用setsockopt函数和sigaction函数分别实现修改网络延时的时长
在Linux系统下,如果使用sigaction将信号SIGCHLD的sa_flags中的SA_NOCLDSTOP选项打开,当子进程停止(STOP作业控制)时, 不产生此信号(即SIGCHLD)。不过,当子进程终止时,仍旧产生此信号(即SIGCHLD)。 3....
10.1.3 Linux信号 10.1.4 中断系统调用 10.2 信号函数 10.2.1 signal系统调用 10.2.2 sigaction系统调用 10.3 信号集 10.3.1 信号集函数 10.3.2 进程信号掩码 10.3.3 被挂起的信号 10.4 统一事件源 10.5 ...
4.2. sigaction 4.3. pause 4.4. 可重入函数 4.5. sig_atomic_t类型与volatile限定符 4.6. 竞态条件与sigsuspend函数 4.7. 关于SIGCHLD信号 34. 终端、作业控制与守护进程 1. 终端 1.1. 终端的基本概念 1.2. 终端...
sa.sa_sigaction_ = SignalHandler; 修改src/base/linuxthreads.cc static void SignalHandler(int signum, siginfo_t *si, void *data) 其中 siginfo_t *si 改成 siginfo *si echo "please modify the src/...
主要有两个函数实现信号的注册:signal()和sigaction()。 2、signal() signal()的函数原型如下: void (*signal(int signum, void (*handler)(int)))(int); 在使用该调用的进程中加入以下头文件: ...
本文通过sigwait()调用来“等待”信号,而通过signal()/sigaction()注册的信号处理函数来“捕获”信号,以体现其同步和异步的区别。 一 概念 1.1 进程与信号 信号是向进程异步发送的软件通知,通
Preeny具有以下模块: 姓名概括发牌器禁用警报() 叉禁用fork() 痕迹禁用ptrace() 德兰禁用rand()和random() 设计禁用sigaction() 脱壳将套接字通信通道传递到控制台desock_dup 将套接字通信通道传送到...
4、在signal.c中我们将会学习到信号处理过程中内核堆栈和用户堆栈的操作过程,对sigaction函数与signal函数有更深入的理解; 5、通过exit.c的学习对系统编程中的kill、waitpid函数会有更深入的理解; 5、mktime.c中...