赞
踩
signal的原理这里不打算多讲,这里主要讲一下应用
man 7 signal,可以看到一些关于signal的介绍:
每个信号都对应着一个action,默认的有:Term, Ign,core,Stop,Cont, 文档上明确的写着是以进程为修改单位的,所有的线程的action都相同:
The signal disposition is a per-process attribute: in a multithreaded application, the disposition of a particular signal is the same for all threads.
信号对应的action被执行了才称之为这个signal被delivered,signal已经发出了,但是没有执行action,称之为signal被pending了,每个线程都可以单独设置mask,来block一些信号,当有对应的signal到来时,这些信号就被pending了,直到再次设置mask在unblock这些signal, pending的signal才会被执行。
signal和默认的action直接的对应关系为:
core就是产生core dump(需要kernel打开coredump选项支持,ulimit -c unlimited不限制core文件大小,core文件的路径可读写),因此可以看出并不是所有的死机都会产生core文件,测试coredump是否生效可以使用下面命令:
kill -s 11 pid
linux有时会出现应用莫名奇妙的死机,死机毫无规律可循,这时就可以考虑捕获信号,如果了解过kernel的原理就会知道死机都是由信号引起的。
捕获信号的本质就是改变action,action其实就是一个函数指针,改变这个函数指针以指向自定义的函数,sigaction(2) or signal(2)都可以进行捕获,但是signal(2)缺乏移植性。
注意这些signal_handler()是在用户空间执行的,内核采用了Trampoline机制,感兴趣的可以查阅相关资料了解一下。
下面给出一个捕获的例子:
- #if DEBUG_SEGV_HANDLER
-
- struct sigaction sa;
- memset(&sa, 0, sizeof(sa));
- sa.sa_sigaction = handle_sigsegv;
- sa.sa_flags = SA_SIGINFO;
- sigaction(SIGSEGV, &sa, NULL);
- sigaction(SIGILL, &sa, NULL);
- sigaction(SIGFPE, &sa, NULL);
- sigaction(SIGBUS, &sa, NULL);
-
- #endif
-
- #if DEBUG_SEGV_HANDLER
- static
- void handle_sigsegv(int sig, siginfo_t *info, void *ucontext)
- {
- long ip;
- ucontext_t *uc;
-
- uc = ucontext;
- ip = uc->uc_mcontext.gregs[REG_EIP];
- fdprintf(2, "signal:%d address:0x%lx ip:0x%lx\n",
- sig,
- /* this is void*, but using %p would print "(null)"
- * even for ptrs which are not exactly 0, but, say, 0x123:
- */
- (long)info->si_addr,
- ip);
- {
- /* glibc extension */
- void *array[50];
- int size;
- size = backtrace(array, 50);
- backtrace_symbols_fd(array, size, 2);
- }
- for (;;) sleep(9999);
- }
- #endif
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。