- 浏览: 1638792 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (405)
- C/C++ (16)
- Linux (60)
- Algorithm (41)
- ACM (8)
- Ruby (39)
- Ruby on Rails (6)
- FP (2)
- Java SE (39)
- Java EE (6)
- Spring (11)
- Hibernate (1)
- Struts (1)
- Ajax (5)
- php (2)
- Data/Web Mining (20)
- Search Engine (19)
- NLP (2)
- Machine Learning (23)
- R (0)
- Database (10)
- Data Structure (6)
- Design Pattern (16)
- Hadoop (2)
- Browser (0)
- Firefox plugin/XPCOM (8)
- Eclise development (5)
- Architecture (1)
- Server (1)
- Cache (6)
- Code Generation (3)
- Open Source Tool (5)
- Develope Tools (5)
- 读书笔记 (7)
- 备忘 (4)
- 情感 (4)
- Others (20)
- python (0)
最新评论
-
532870393:
请问下,这本书是基于Hadoop1还是Hadoop2?
Hadoop in Action简单笔记(一) -
dongbiying:
不懂呀。。
十大常用数据结构 -
bing_it:
...
使用Spring MVC HandlerExceptionResolver处理异常 -
一别梦心:
按照上面的执行,文件确实是更新了,但是还是找不到kernel, ...
virtualbox 4.08安装虚机Ubuntu11.04增强功能失败解决方法 -
dsjt:
楼主spring 什么版本,我的3.1 ,xml中配置 < ...
使用Spring MVC HandlerExceptionResolver处理异常
信号2:
1、信号集合:
信号集合以及其操作我们经常遇到,比如设置一些进程要阻塞的信号,进程的信号pending集合。
以下是常用的信号操作:
sigemptyset用于初始化一个信号集合为空集合。sigfillset初始化信号集合为包含所有信号的集合。
返回0。
sigaddset将signo信号添加到信号集合中,sigdelset将signo从信号集合中删除。成功返回0,失败返回
-1,并将errno设置为EINVAL,表示signo不是一个合法的信号标识符。
sigismember返回1如果在信号集中,0如果不在,-1错误,并设置errno为EINVAL。
Linux提供了另外的一个非标准POSIX的信号集合操作函数:
sigisemptyset 返回1 如果信号集是空,否则返回0
sigorset left和right两个信号集的并集。
sigandset left和right两个信号集的交集。
2、阻塞信号:
如果我们的程序需要在信号处理程序和程序其他部分共享数据,如果我们的程序中的某些部分在运行期间不希望被
信号中断(包括来自信号处理程序的中断),我们把不希望中断的部分成为临界区,我们可以通过临时挂起信号来
保护它。
我们称这些信号被阻塞,任何被挂起的信号都得不到处理,直到被解除阻塞,进程可以阻塞任意多个信号。
信号掩码就是要阻塞的信号集。一个信号集可以查看它的掩码,修改它的掩码,或者同时做这两个操作,
segprocmask提供这些操作:
1)设置信号掩码
sigprocmask的行为取决于how的值,它是一下标示之一:
SIG_SETMASK 调用进程的信号掩码变成set。
SIG_BLOCK set中的信号被加入到调用信号的掩码中。也就是说,信号掩码编程了当前信号掩码和set的并集。
SIG_UNBLOCK set中的信号集合被从调用进程的信号掩码中移除。
如果oldset是非空,该函数将oldset设置为先前的信号集。
如果set是空的,该函数忽略how,并且不改变信号掩码,但仍然设置信号掩码。给set一个空值是检测当前
信号的一个方法。
调用成功,返回0,失败返回-1,把errno设置为EINVAL,表明how是无效的,或者设置为EFAULT,表示set或者
oldset为无效指针。
阻塞SIGKILL或者SIGSTOP是不允许的。
例子(查看当前进程的signal mask):
2)获取待处理信号:
当内核产生一个被阻塞的信号时,该信号未被发送。我们把它叫做待处理信号。当一个待处理信号解除
阻塞时,内核会把它发送给进程处理:
待处理的信号是 介于发送和处理之间的状态。
POSIX定义了获取待处理信号的函数:
成功将set设置为待处理的信号集返回,并返回0,失败返回-1。
下面例子展示了一些信号的使用方法:
这个进程阻塞了SIGQUIT,保存了当前的信号掩码,然后休眠5秒钟,任何在这期间发生的quit信号都会被阻塞,
直到信号被解除阻塞,然后休眠5秒,我们可以查看它是处于pending还是解除阻止状态。
注意:在程序中我们首先保存了就得掩码,然后设置SIGQUIT被阻塞,然后使用SIG_SETMASK来恢复以前的掩码。
可选择的我们可以把我们阻塞的SIGQUIT通过SIG_UNBLOCK来恢复,但是这样可能会有问题,因为之前SIGQUIT
可能已经被设置阻塞。
运行:
$ ./a.out
^\
SIGQUIT pending
caught SIGQUIT
SIGQUIT unblocked
^\Quit(coredump)
$ ./a.out
^\^\^\^\^\
SIGQUIT pending
caught SIGQUIT
SIGQUIT unblocked
^\Quit(coredump)
可见信号并不是排在信号队列中,而是合并为一次。
3)等待信号集:
我们已经知道了如何改变信号掩码来阻塞和解除阻塞指定的信号。我们可以使用这个技术来保护临界区,来防止
被信号终端。如果我们想解除阻塞一个信号,然后pause,等待刚才阻塞的信号发生,该怎么做?假设信号时SIGINT,
我们可能写下如下代码:
这段代码时存在问题的:
如果信号发生在sigpromask之后,pause之前,则会丢失,pause会阻塞。解决的方法是还原信号和pause作为一个原子操作。
sigsuspend提供了这个功能。它可以临时改变信号掩码,该函数始终处于等待状态,直到产生一个终止进程或者被该进程处理的信号。
如果一个信号终止了进程,sigsuspend不返回,如果一个信号被发送并且处理了,sigsuspend在信号处理函数返回后
,返回-1,并将errno改为EINTR,如果set是一个无效指针,errno被设置为EFAULT。
一般在获得已经到达的信号和在程序运行期间阻塞在临界区信号时使用。进程首先sigprocmask来阻塞一个信号集,
将旧的信号掩码保存在oldset中。退出临界区后,进程会调用sigsuspend,将oldset赋值给set。
下面代码展示了使用sigsuspend来保护临界区:
$ ./a.out
program start:
in critical region: SIGINT
^?
in sig_int: SIGINT SIGUSR1
after return from sigsuspend: SIGINT
program exit:
当我们调用sigsuspend的时候我们添加了SIGUSR1掩码,当sigsuspend返回时,它恢复了以前的掩码。
3、高级信号管理:
signal是一个很基本管理信号的函数,因为他是标准C的库,所以它只能对操作系统做最小的假设,它
只提供了最低限度的信号管理的标准。POSIX定义了sigaction系统调用,它提供了更强大的信号管理能力。
除此之外,当信号处理程序运行时,你可以用它来阻塞特定的信号的接收,获取信号发送时各种操作系统和
进程状态的信息:
调用sigaction会改变由signo表示信号的action,signo可以是出了SIGKILL和SIGSTOP外的任何信号。如果act
非空,该系统调用将该信号当前的行为替换成由act指定的行为。如果oldact是非空,该调用会先存储以前
给定的信号action。
sigaction接口允许精细的控制信号的结构。
sa_hanlder指定了接收到信号时采取的操作。和signal一样,该域可以是SIG_DEF,SIG_IGN,或者自定义的
处理函数,原型和sigaction一样:
如果sa_flags被设置成SA_SIGINFO,那么将由sa_sigaction而不是sa_handler指定信号处理函数。该信号原型
略有不同:
signo信号编号,siginfo_t结构作为第二个参数,ucontext_t结构作为第三个参数。
有些系统sa_handler和sa_sigaction是一个联合,所以不能给这两个域同时赋值。
sa_mask提供了应该在执行信号处理程序时被阻塞的信号集。这使得程序为多个信号处理程序间重入提供了适当
的保护。当前信号是被阻塞的以防止信号嵌套发送,除非sa_flags设置了SA_NODEFER标志。
当处理函数返回时sa_mask会被重置。
SA_NOCLDSTOP
If signo is SIGCHLD, this flag instructs the system to not provide notification when
a child process stops or resumes.
SA_NOCLDWAIT
If signo is SIGCHLD, this flag enables automatic child reaping: children are not converted
to zombies on termination, and the parent need not (and cannot) call wait( )
on them. See Chapter 5 for a lively discussion of children, zombies, and wait( ).
SA_NOMASK
This flag is an obsolete non-POSIX equivalent to SA_NODEFER (discussed earlier in
this section). Use SA_NODEFER instead of this flag, but be prepared to see this
value turn up in older code.
SA_ONESHOT
This flag is an obsolete non-POSIX equivalent to SA_RESETHAND (discussed later in
this list). Use SA_RESETHAND instead of this flag, but be prepared to see this value
turn up in older code.
SA_ONSTACK
This flag instructs the system to invoke the given signal handler on an alternative
signal stack, as provided by sigaltstack( ). If you do not provide an alternative
stack, the default is used—that is, the system behaves as if you did not provide
this flag. Alternative signal stacks are rare, although they are useful in some
pthreads applications with smaller thread stacks that might be overrun by some
signal handler usage. We do not further discuss sigaltstack( ) in this book.
SA_RESTART
This flag enables BSD-style restarting of system calls that are interrupted by signals.
SA_RESETHAND
This flag enables “one-shot” mode. The behavior of the given signal is reset to
the default once the signal handler returns.
siginfo_t结构:
POSIX.1兼容的实现至少包含si_signo和si_sigcode。
si_code:
sig_code字段指示了信号的原因。对于用户发送的信号,该域说明了信号是如何被发送的,对于内核信号
该域说明了信号是为什么被发送的。
详细可参见APUE p327 Figure 10.7 siginfo_t code values.
我们可以使用sigaction来实现signal函数:
我们将所有的信号除了SIGALARM都设置了SA_RESTART的flag,以为我们不想让SIALARM restart,这样可以为I/O
操作设置超时时间。
4、发送带附加信息的信号:
我们看到当信号注册设置了SA_SIGINFO的flag后,siginfo结构的si_value提供了一些附加的信息。
有POSIX定义的sigqueue函数,允许进程发送带附加信息的信号,这样我们可以从siginfo中得到这个值:
这个和kill的运行方式很像。成功时由signo表示的信号被加入到由pid指定的进程或者进程队列中,
并返回0。附加的信息由sigval指定,他是一个整数和void指针的联合:
例子:
5、abort函数:
abort函数会导致进程非正常终止:
这个函数向调用者发送SIGABRT信号。进程不应该忽略这个信号。
abort实现:
参考:
1、《Linux system programming》
2、《Unix system programming》
3、《Advanced Programming in the Unix Environment》
1、信号集合:
信号集合以及其操作我们经常遇到,比如设置一些进程要阻塞的信号,进程的信号pending集合。
以下是常用的信号操作:
#include <signal.h> int sigemptyset(sigset_t *set); int sigfillset(sigset_t *set); int sigaddset(sigset_t *set, int signo); int sigdelset(sigset_t *set, int signo); int sigismember(const sigset *set, int signo);
sigemptyset用于初始化一个信号集合为空集合。sigfillset初始化信号集合为包含所有信号的集合。
返回0。
sigaddset将signo信号添加到信号集合中,sigdelset将signo从信号集合中删除。成功返回0,失败返回
-1,并将errno设置为EINVAL,表示signo不是一个合法的信号标识符。
sigismember返回1如果在信号集中,0如果不在,-1错误,并设置errno为EINVAL。
Linux提供了另外的一个非标准POSIX的信号集合操作函数:
#include <signal.h> int sigisemptyset(sigset_t *set); int sigorset(sigset_t *dest, sigset_t *left, sigset_t *right); int sigandset(sigset_t *dest, sigset_t *left, sigset_t *right);
sigisemptyset 返回1 如果信号集是空,否则返回0
sigorset left和right两个信号集的并集。
sigandset left和right两个信号集的交集。
2、阻塞信号:
如果我们的程序需要在信号处理程序和程序其他部分共享数据,如果我们的程序中的某些部分在运行期间不希望被
信号中断(包括来自信号处理程序的中断),我们把不希望中断的部分成为临界区,我们可以通过临时挂起信号来
保护它。
我们称这些信号被阻塞,任何被挂起的信号都得不到处理,直到被解除阻塞,进程可以阻塞任意多个信号。
信号掩码就是要阻塞的信号集。一个信号集可以查看它的掩码,修改它的掩码,或者同时做这两个操作,
segprocmask提供这些操作:
1)设置信号掩码
#include <signal.h> int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
sigprocmask的行为取决于how的值,它是一下标示之一:
SIG_SETMASK 调用进程的信号掩码变成set。
SIG_BLOCK set中的信号被加入到调用信号的掩码中。也就是说,信号掩码编程了当前信号掩码和set的并集。
SIG_UNBLOCK set中的信号集合被从调用进程的信号掩码中移除。
如果oldset是非空,该函数将oldset设置为先前的信号集。
如果set是空的,该函数忽略how,并且不改变信号掩码,但仍然设置信号掩码。给set一个空值是检测当前
信号的一个方法。
调用成功,返回0,失败返回-1,把errno设置为EINVAL,表明how是无效的,或者设置为EFAULT,表示set或者
oldset为无效指针。
阻塞SIGKILL或者SIGSTOP是不允许的。
例子(查看当前进程的signal mask):
#include <signal.h> #include <unistd.h> #include <stdio.h> void pr_mask(const char *str){ sigset_t sigset; int errno_save; errno_save = errno; if(sigprocmask(0,NULL,&sigset) < 0){ perror("sigprocmask"); return 1; } printf("%s",str); if(sigismember(&sigset,SIGINT)) printf("SIGINT"); if(sigismember(&sigset,SIGQUIT)) printf("SIGQUIT"); if(sigismember(&sigset,SIGUSR1)) printf("SIGUSR1"); if(sigismember(&sigset,SIGALARM)) printf("SIGALARM"); printf("\n"); errno = errno_save; }
2)获取待处理信号:
当内核产生一个被阻塞的信号时,该信号未被发送。我们把它叫做待处理信号。当一个待处理信号解除
阻塞时,内核会把它发送给进程处理:
待处理的信号是 介于发送和处理之间的状态。
POSIX定义了获取待处理信号的函数:
#include <signal.h> int sigpending(sigset_t *set);
成功将set设置为待处理的信号集返回,并返回0,失败返回-1。
下面例子展示了一些信号的使用方法:
#include <signal.h> #include <unistd.h> #include <stdio.h> stati void sig_quit(int); int main(void){ sigset_t newmask,oldmask,pendmask; if(signal(SIGQUIT,sig_quit) == SIG_ERR){ perror("signal"); return 1; } sigemptyset(&newmask); sigaddset(&newmask,SIGQUIT); if(sigprocmask(SIG_BLOCK,&newmask,&oldmask) < 0){ perror("sigprocmask"); return 1; } sleep(5); if(sigpending(&pendmask) < 0){ perror("sigprocmask"); return 1; } if(sigismember(&pendmask,SIGQUIT)){ printf("\nSIGQUIT pending\n"); return 1; } if(sigprocmask(SIG_SETMASK,&oldmask,NULL) < 0){ perror("sigprocmask"); return 1; } printf("SIGQUIT unblocked\n"); sleep(5); exit(0); } static void sig_quit(int signo){ printf("caught SIGQUIT\n"); if( signal(SIGQUIT, SIG_DEL) == SIG_ERR) perror("SIGQUIT"); }
这个进程阻塞了SIGQUIT,保存了当前的信号掩码,然后休眠5秒钟,任何在这期间发生的quit信号都会被阻塞,
直到信号被解除阻塞,然后休眠5秒,我们可以查看它是处于pending还是解除阻止状态。
注意:在程序中我们首先保存了就得掩码,然后设置SIGQUIT被阻塞,然后使用SIG_SETMASK来恢复以前的掩码。
可选择的我们可以把我们阻塞的SIGQUIT通过SIG_UNBLOCK来恢复,但是这样可能会有问题,因为之前SIGQUIT
可能已经被设置阻塞。
运行:
$ ./a.out
^\
SIGQUIT pending
caught SIGQUIT
SIGQUIT unblocked
^\Quit(coredump)
$ ./a.out
^\^\^\^\^\
SIGQUIT pending
caught SIGQUIT
SIGQUIT unblocked
^\Quit(coredump)
可见信号并不是排在信号队列中,而是合并为一次。
3)等待信号集:
我们已经知道了如何改变信号掩码来阻塞和解除阻塞指定的信号。我们可以使用这个技术来保护临界区,来防止
被信号终端。如果我们想解除阻塞一个信号,然后pause,等待刚才阻塞的信号发生,该怎么做?假设信号时SIGINT,
我们可能写下如下代码:
sigset_t newmask, oldmask; sigemptyset(&newmask); sigaddset(&newmask,SIGINT); if(sigprocmask(SIG_BLOCK,&newmask,&oldmask) < 0){ perror("sigprocmask"); return 1; } /* critical region of code*/ /* reset signal mask, whick is unblocks SIGINT */ if(sigprocmask(SIG_SETMASK,&oldmask,NULL) < 0){ perror("sigprocmask"); return 1; } /* wait for signal to occur */ pause();
这段代码时存在问题的:
如果信号发生在sigpromask之后,pause之前,则会丢失,pause会阻塞。解决的方法是还原信号和pause作为一个原子操作。
sigsuspend提供了这个功能。它可以临时改变信号掩码,该函数始终处于等待状态,直到产生一个终止进程或者被该进程处理的信号。
#include <signal.h> int sigsuspend(const sigset_t *set);
如果一个信号终止了进程,sigsuspend不返回,如果一个信号被发送并且处理了,sigsuspend在信号处理函数返回后
,返回-1,并将errno改为EINTR,如果set是一个无效指针,errno被设置为EFAULT。
一般在获得已经到达的信号和在程序运行期间阻塞在临界区信号时使用。进程首先sigprocmask来阻塞一个信号集,
将旧的信号掩码保存在oldset中。退出临界区后,进程会调用sigsuspend,将oldset赋值给set。
下面代码展示了使用sigsuspend来保护临界区:
#include <unistd.h> #include <signal.h> #include <stdio.h> static void sig_int(int); int main(void){ sigset_t newmask,oldmask,waitmask; pr_mask("program start:");//前面我们定义的打印信号掩码的函数 if(signal(SIGINT, sig_int) == SIG_ERR){ perror("signal"); return 1; } sigemptyset(&waitmask); sigaddset(&waitmask,SIGUSR1); sigemtpyset(&newmask); sigaddset(&newmask,SIGINT); /* block SIGINT and save current signal mask */ if(sigprocmask(SIG_BLOCK,&newmask,&oldmask) < 0){ perror("sigprocmask"); return 1; } pr_mask("in critical region: "); /* pause, allowing all signals except SIGUSR1. */ if(sigsuspend(&waitmask) != -1){ perror("sigsuspend"); return 1; } pr_mask("after return from sigsuspend:"); /* reset signal mask with unblock SIGINT */ if(sigmaskproc(SIG_SETMASK,&oldmask,NULL) < 0){ perror("sigmaskproc"); return 1; } pr_mask("program exit:"); exit(0); }
$ ./a.out
program start:
in critical region: SIGINT
^?
in sig_int: SIGINT SIGUSR1
after return from sigsuspend: SIGINT
program exit:
当我们调用sigsuspend的时候我们添加了SIGUSR1掩码,当sigsuspend返回时,它恢复了以前的掩码。
3、高级信号管理:
signal是一个很基本管理信号的函数,因为他是标准C的库,所以它只能对操作系统做最小的假设,它
只提供了最低限度的信号管理的标准。POSIX定义了sigaction系统调用,它提供了更强大的信号管理能力。
除此之外,当信号处理程序运行时,你可以用它来阻塞特定的信号的接收,获取信号发送时各种操作系统和
进程状态的信息:
#include <signal.h> int sigaction(int signo, const struct sigaction *act, struct sigaction *oldact);
调用sigaction会改变由signo表示信号的action,signo可以是出了SIGKILL和SIGSTOP外的任何信号。如果act
非空,该系统调用将该信号当前的行为替换成由act指定的行为。如果oldact是非空,该调用会先存储以前
给定的信号action。
sigaction接口允许精细的控制信号的结构。
struct sigaction{ void (*sa_handler)(int); /*addr of signal handler */ void (*sa_sigaction)(int siginfo_t *, void *);/* alternate handler */ sigset_t sa_mask; /*signals to block */ int sa_flags; /* flags */ void (*sa_restorer)(void); /* obsolete and non-POSIX */ };
sa_hanlder指定了接收到信号时采取的操作。和signal一样,该域可以是SIG_DEF,SIG_IGN,或者自定义的
处理函数,原型和sigaction一样:
void my_handler(int signo);
如果sa_flags被设置成SA_SIGINFO,那么将由sa_sigaction而不是sa_handler指定信号处理函数。该信号原型
略有不同:
void my_handler(int signo, siginfo_t *si, void *ucontext);
signo信号编号,siginfo_t结构作为第二个参数,ucontext_t结构作为第三个参数。
有些系统sa_handler和sa_sigaction是一个联合,所以不能给这两个域同时赋值。
sa_mask提供了应该在执行信号处理程序时被阻塞的信号集。这使得程序为多个信号处理程序间重入提供了适当
的保护。当前信号是被阻塞的以防止信号嵌套发送,除非sa_flags设置了SA_NODEFER标志。
当处理函数返回时sa_mask会被重置。
cpp 写道
SA_NOCLDSTOP
If signo is SIGCHLD, this flag instructs the system to not provide notification when
a child process stops or resumes.
SA_NOCLDWAIT
If signo is SIGCHLD, this flag enables automatic child reaping: children are not converted
to zombies on termination, and the parent need not (and cannot) call wait( )
on them. See Chapter 5 for a lively discussion of children, zombies, and wait( ).
SA_NOMASK
This flag is an obsolete non-POSIX equivalent to SA_NODEFER (discussed earlier in
this section). Use SA_NODEFER instead of this flag, but be prepared to see this
value turn up in older code.
SA_ONESHOT
This flag is an obsolete non-POSIX equivalent to SA_RESETHAND (discussed later in
this list). Use SA_RESETHAND instead of this flag, but be prepared to see this value
turn up in older code.
SA_ONSTACK
This flag instructs the system to invoke the given signal handler on an alternative
signal stack, as provided by sigaltstack( ). If you do not provide an alternative
stack, the default is used—that is, the system behaves as if you did not provide
this flag. Alternative signal stacks are rare, although they are useful in some
pthreads applications with smaller thread stacks that might be overrun by some
signal handler usage. We do not further discuss sigaltstack( ) in this book.
SA_RESTART
This flag enables BSD-style restarting of system calls that are interrupted by signals.
SA_RESETHAND
This flag enables “one-shot” mode. The behavior of the given signal is reset to
the default once the signal handler returns.
siginfo_t结构:
#include <sys/signal.h> typedef struct siginfo_t{ int si_signo; /*signal number*/ int si_errno; /* if nozero, errno value from <errno.h> */ int si_code; /*signal code*/ pid_t si_pid; /* sending process's PID */ uid_t si_uid; /* sending process's real UID */ int si_status; /* exit value or signal */ clock_t si_utime; /* user time consumed */ clock_t si_stime; /* system time consumed */ sigval_t si_value; /* signal payload value */ int sig_int; /* POSIX.1b signal */ void *si_ptr; /* POSIX.1b signal */ void *si_addr; /* memory location that cause fault */ int si_band; /*band event*/ int si_fd; /* file descriptor */ };
POSIX.1兼容的实现至少包含si_signo和si_sigcode。
si_code:
sig_code字段指示了信号的原因。对于用户发送的信号,该域说明了信号是如何被发送的,对于内核信号
该域说明了信号是为什么被发送的。
详细可参见APUE p327 Figure 10.7 siginfo_t code values.
我们可以使用sigaction来实现signal函数:
#include <signal.h> SigFunc * signal(int signo,SigFunc * func){ struct sigaction act,oact; act.sa_handler = func; sigemptyset(&act.sa_mask); act.sa_flags = 0; if(signo == SIGALARM){ #ifdef SA_INTERRUPT act.sa_flag |= SA_INTERRUPT; #endif }else{ #ifdef SA_RESTART act.sa_flag |= SA_RESTART; #endif } if(sigaction(signo,&act,&oact) < 0) return SIG_ERR; return (oact.sa_handler); }
我们将所有的信号除了SIGALARM都设置了SA_RESTART的flag,以为我们不想让SIALARM restart,这样可以为I/O
操作设置超时时间。
4、发送带附加信息的信号:
我们看到当信号注册设置了SA_SIGINFO的flag后,siginfo结构的si_value提供了一些附加的信息。
有POSIX定义的sigqueue函数,允许进程发送带附加信息的信号,这样我们可以从siginfo中得到这个值:
#include <signal.h> int sigqueue(pid_t pid, int signo, const union sigval value);
这个和kill的运行方式很像。成功时由signo表示的信号被加入到由pid指定的进程或者进程队列中,
并返回0。附加的信息由sigval指定,他是一个整数和void指针的联合:
union sigval{ int sival_int; void *sival_ptr; },
例子:
sigval value; int ret; value.sival_int = 404; ret = sigqueue(1722,SIGUSR2,value); if(ret) perror("sigqueue");
5、abort函数:
abort函数会导致进程非正常终止:
#include <stdlib.h> void abort(void)
这个函数向调用者发送SIGABRT信号。进程不应该忽略这个信号。
abort实现:
#include <signal.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> void abort(void){ sigset_t mask; struct sigaction action; /* Caller can't ignore a SIGABRT, if so reset to default */ sigaction(SIGABRT,NULL,&action); if(&action.sa_handler == SIG_IGN){ action.sa_handler = SIG_DFL; sigaction(SIGABRT,&action,NULL); } if(action.sa_handler == SIG_DFL){ fflush(NULL);/* flush all open stdio stream */ } /* caller can't block SIGABRT; make sure it's unblocked */ sigfillset(&mask); sigdelset(&mask,SIGABRT); sigprocmask(SIG_SETMASK,&mask,NULL); kill(getpid(),SIGABRT); /* If we're here,process caught SIGABRT and returned */ /* 如果信号被捕获,返回之后需要将handler设置为SIG_DFL,保证调用abort会终止进程*/ fflush(NULL); /* flush all open stdio stream */ action.sa_handler = SIG_DFL; sigaction(SIGABRT,&action, NULL); /* reset to default */ sigprocmask(SIG_SETMASK,&mask,NULL);/* just in case ...*/ kill(getpid(),SIGABRT);/* and one more time ...*/ exit(1); }
参考:
1、《Linux system programming》
2、《Unix system programming》
3、《Advanced Programming in the Unix Environment》
发表评论
-
【zz】Vim的分屏
2012-04-26 11:13 1551分屏启动Vim 使用大写 ... -
bash的几种for循环
2012-04-26 11:13 17961、罗列式 for VARIABLE in 1 2 3 ... -
【zz】几个简单选项让你的Readline(Bash)更好用
2011-10-10 23:08 2379Reddit上的一位仁兄贴出了他的readline手册学习成果 ... -
pipe in -exec
2011-09-27 22:35 1392一个简单的例子: 将一堆的.txt文件,合并成一个文件,让每个 ... -
[zz]Unix调试的瑞士军刀:lsof
2011-08-31 10:33 1470原文见:http://heikezhi.com/2011/06 ... -
[zz]关于xargs,你可能不知道的
2011-08-29 23:05 2429如果你曾经花了许多时间在Unix命令行上,那么或许你已经见过x ... -
使用scala.sys.process包和系统交互
2011-07-19 00:00 6446在Java中我们可以使用Runtime.getRuntime( ... -
virtualbox 4.08安装虚机Ubuntu11.04增强功能失败解决方法
2011-06-23 22:17 14411在笔记本安装Ubuntu11.04增强功能失败 引用 fuli ... -
awk getline
2011-06-02 23:58 5778awk getline开始一直用做按行读取文件。 getlin ... -
[zz]服务器性能评估
2011-04-29 14:17 3990工作这么久了,主 ... -
[zz]Top命令VIRT,RES,SHR,DATA的含义
2011-04-10 15:50 4068VIRT:virtual memory usage ... -
[zz]一些shell命令
2011-04-10 15:35 14681.显示消耗内存/CPU最多的10个进程 ps aux | ... -
Open VPN免密码配置
2011-03-03 22:55 3589公司VPN的帐号密码使用的是个超长的随机数,每次输入很麻烦,如 ... -
Linux下使用RTX腾讯通
2011-03-03 22:46 10741在公司为了使用RTX,专门安装了一个XP的虚拟机,但是这个也不 ... -
[zz]linux 常用命令总结:
2010-12-11 21:30 1658linux 常用命令总结: 一。 通用命令: 1. dat ... -
Ubuntu10.10解决Empathy无法链接MSN的问题
2010-10-21 16:36 37191.在Empathy中删除无法登录的MSN账户,并关闭Empa ... -
[zz]Vim的分屏功能
2010-10-21 13:09 1648分屏启动Vim 使用大写 ... -
Ubuntu10.10 64bit使用Eclipse插件subclipse问题
2010-10-20 20:32 1936升级到ubuntu10.10什么坑都碰到了,郁闷啊。发现sub ... -
scim输入法,Eclipse代码提示之后失去焦点的问题
2010-10-20 13:36 3057突然发现Eclipse,每次代码提示之后无法打字,感觉是文本域 ... -
Linux下使用谷歌输入法
2010-10-18 23:01 3088Linux的中文输入法一直太烂,scim终于出来对google ...
相关推荐
操作系统:LInux、树莓派、安卓开发、微机操作系统、网络操作系统、分布式操作系统等。此外,还有嵌入式操作系统、智能操作系统等。 网络与通信:数据传输、信号处理、网络协议、网络与通信硬件、网络安全网络与通信...
Posix多线程编程学习笔记1~6,包括线程基础,线程属性,信号灯,条件变量,互斥变量,共享内存六部分内容。很有助于linux下多线程的开发。文档主要包含介绍相应的pthread接口函数,并举了部分相应的例子。
虽然这本书并不是专门讲解Linux操作系统的linux学习书籍嵌入式linux 培训,但它对于理解Unix/Linux系统编程以及深入理解操作系统原理都有很大帮助。该书主要介绍Unix环境下高级编程的相关知识,如进程控制、信号处理...
《Linux 高性能服务器编程》和《Linux多线程服务端编程:使用muduo C++网络库》的笔记和源码,以及两个轻量级服务器的项目代码 软件开发设计:应用软件开发、系统软件开发、移动应用开发、网站开发C++、Java、python...
Linux学习笔记(一) Linux学习笔记(二) Linux学习笔记(三):函数、文件IO和线程 目录复习结构体:struct文件I/O:线程:主要学习内容信号量同步:按照一定的顺序有序的执行互斥:抢资源;谁先抢到资源就谁先执行...
C#学习笔记(2)【大 中 小】【打印】【加入收藏】【关闭】 【收藏到新浪ViVi】【收藏到365KEY】 浏览字号:日期:2004-07-11 人气:8092 出处: write by cash(天下第七) 2002.01.20 版权所有,翻录不究 cashcao@...
第一阶段在PC机上学习熟悉Linux. 一.Red Hat Linux 9下的常用操作… ………………… 二.Minicom的使用….… 三.NFS的使用… … 四.应用程序编程实验…… 五.模块编程实验…… 六.简单的字符设备驱动实验…… 第二...
这个是我在学习Linux的时候做的思维导图笔记,主要是Linux的一些基础知识。免费提供下载,学习分享。 该文档分为以下几个部分: 1.shell语法:包含格式化输入输出、数组定义、变量定义方法、运算方法、流程控制、...
(牛客网C++课程)Linux 高并发Web服务器项目实战(带定时检测代码) 技术框架: 1. 线程池 + 非阻塞 socket + epoll + 事件处理的并发模型 2. 状态机解析HTTP请求 3. 心跳机制 4. 简易日志系统 主要内容: 1. ...
这是我学习Unix(主要是linux)系统编程与网络编程的笔记,附上部分源码 系统编程 进程 创建fork 执行exec 销毁wait/waitpid(SIGCHLD) 进程间通信: 匿名管道pipe,命名管道(FIFO)mkfifo System V IPC(还有一组POSIX...
最主要的是学习什么课程::《电工电路基础》《低频电子线路》《数字电路》《高频电子 线路》《电子测量》《智能仪器原理及应用》《传感器技术》《电机与电气控制》《信号与系统》《 单片机接口原理及应用》等等。...
快来学习编程和设计用于声音艺术和音乐表演的基于计算机的系统。 Shawn 将介绍开源可视化编程语言 Pd 的基础知识; 并专注于开发具有声音合成和信号处理参数实时手势控制功能的乐器。 参与方式:下载并安装 Pd-...