背景介绍
Linux分为内核态和用户态,用户态通过系统调用(syscall)进入内核态执行。
用户空间的glibc库将Linux内核系统调用封装成GNU C Library库文件(兼容ANSI & POSIX C语言标准),同时提供了其他特性的支持。
应用程序通常不是直接调用Linux内核的系统调用接口,而是通过glibc库封装的接口间接调用Linux内核系统调用。
信号量机制
关于Linux信号量机制的原理,建议阅读《Unix环境高级编程》第10章,本博客只是简单介绍其原理。
信号量是一种软中断,用来实现Linux内核和应用程序之间的异步通信。
Linux支持大概380种信号量,每一个信号量由一个4字节整形数据表示。可以通过man signals查看所有信号量描述。其中1~32号信号量是从Unix继承而来,33~64是Linux内核定义的信号量。
信号量处理函数可以在应用程序中自定义,如果没有自定义,则链接glibc中默认的信号量处理函数。应用程序也可以屏蔽指定信号量。
信号量触发情况有三种:
1)Linux内核检测到应用程序异常,发送特定的信号量给应用程序,应用程序捕获到信号量后,调用信号量处理函数;
2)Linux内核因为内部事件而给应用程序发送特定信号,通知应用程序发生了某个事件,如著名的segmentation fault,应用程序捕获到信号量后,调用信号量处理函数;
3)Linux内核检测到外部事件,如Ctrl+C,Ctrl+Z等,发送特定信号给应用程序,应用程序捕获到信号量后,调用信号量处理函数;
常见信号量介绍
Signal Standard Action Comment
────────────────────────────────────────────────────────────────────────
SIGABRT P1990 Core Abort signal from abort(3) SIGABRT信号由abort()系统调用产生,通常是glibc库检测到应用程序异常,主动触发的
SIGALRM P1990 Term Timer signal from alarm(2)
SIGBUS P2001 Core Bus error (bad memory access) SIGBUS指总线访问错误,通常是因为地址不对齐导致,如奇地址;
SIGCHLD P1990 Ign Child stopped or terminated SIGCHLD是子线程终止执行时发送给主进程的信号量
SIGCLD - Ign A synonym for SIGCHLD
SIGCONT P1990 Cont Continue if stopped
SIGEMT - Term Emulator trap
SIGFPE P1990 Core Floating-point exception
SIGHUP P1990 Term Hangup detected on controlling terminal
or death of controlling process
SIGILL P1990 Core Illegal Instruction SIGILL非法指令错误,可能是程序跑飞的情况或者不兼容代码
SIGINFO - A synonym for SIGPWR
SIGINT P1990 Term Interrupt from keyboard
SIGIO - Term I/O now possible (4.2BSD)
SIGIOT - Core IOT trap. A synonym for SIGABRT
SIGKILL P1990 Term Kill signal SIGKILL通常是通过kill -9 <pid>手动杀死进程时触发的信号量;
SIGLOST - Term File lock lost (unused)
SIGPIPE P1990 Term Broken pipe: write to pipe with no
readers; see pipe(7)
SIGPOLL P2001 Term Pollable event (Sys V).
Synonym for SIGIO
SIGPROF P2001 Term Profiling timer expired
SIGPWR - Term Power failure (System V)
SIGQUIT P1990 Core Quit from keyboard
SIGSEGV P1990 Core Invalid memory reference SIGSEGV指非法内存访问,通常出现在栈溢出、野指针或者空指针的情况;
SIGSTKFLT - Term Stack fault on coprocessor (unused)
SIGSTOP P1990 Stop Stop process
SIGTSTP P1990 Stop Stop typed at terminal
SIGSYS P2001 Core Bad system call (SVr4);
see also seccomp(2)
SIGTERM P1990 Term Termination signal
SIGTRAP P2001 Core Trace/breakpoint trap SIGTRAP信号量通常用于进行插桩调试,如gdb调试时插入断点等
SIGTTIN P1990 Stop Terminal input for background process
SIGTTOU P1990 Stop Terminal output for background process
SIGUNUSED - Core Synonymous with SIGSYS
SIGURG P2001 Ign Urgent condition on socket (4.2BSD)
SIGUSR1 P1990 Term User-defined signal 1
SIGUSR2 P1990 Term User-defined signal 2
SIGVTALRM P2001 Term Virtual alarm clock (4.2BSD)
SIGXCPU P2001 Core CPU time limit exceeded (4.2BSD);
see setrlimit(2)
SIGXFSZ P2001 Core File size limit exceeded (4.2BSD);
see setrlimit(2)
SIGWINCH - Ign Window resize signal (4.3BSD, Sun)
信号量进阶
关于自定义Linux信号量处理函数、屏蔽指定信号量等操作,参考《System Programing: Signals》
信号量处理函数实质上是应用程序发生异常时的一种修复或者调试机制,因为信号量处理不是正常的函数调用,因此它会复用父函数的栈,如果信号量处理函数中发生了异常,系统是没有办法处理的,因此,信号量处理函数必须是安全可靠的。
自定义的信号量处理函数不可以做信号量同步(防止死锁),但是可以通过call fork起gdb调试器或者写log文件到磁盘。