日期:2014-05-16 浏览次数:20651 次
1. 前言 信号是类UNIX系统中一个重要的进程控制方法,向中断一样,可通过向进程发送不同的信号临时中断 程序的正常运行而进入信号处理程序或执行缺省的信号响应,如重新更新程序配置、终止进程等。 在用户空间中,信号处理接口是通过一系列系统调用来实现的,包括signal, sigaction, sigsuspend, sigaltstack等,进程可通过以上这些接口定义进程的信号处理函数。如果要向其他进 程发信号,可通过kill系统调用实现。 在内核中对信号的处理程序主要定义在 kernel/signal.c, arch/***/kernel/signal.c等文件中,头 文件在 include/linux/signal.h, include/asm/signal.h等。 以下内核代码版本为2.6.19.2。 2. 数据结构 2.1 信号自身基本定义 用于定义信号处理 /* include/asm-generic/signal.h */ // 信号处理函数格式 typedef void __signalfn_t(int); typedef __signalfn_t __user *__sighandler_t; // 信号恢复函数 typedef void __restorefn_t(void); typedef __restorefn_t __user *__sigrestore_t; // 三个预定义的信号处理函数值 #define SIG_DFL ((__force __sighandler_t)0) /* default signal handling */ #define SIG_IGN ((__force __sighandler_t)1) /* ignore signal */ #define SIG_ERR ((__force __sighandler_t)-1) /* error return from signal */ /* include/asm-i386/signal.h */ #define _NSIG 64 #define _NSIG_BPW 32 #define _NSIG_WORDS (_NSIG / _NSIG_BPW) typedef unsigned long old_sigset_t; /* at least 32 bits */ // 信号集, 最多64个信号 typedef struct { unsigned long sig[_NSIG_WORDS]; } sigset_t; // 老的信号处理结构 struct old_sigaction { __sighandler_t sa_handler; old_sigset_t sa_mask; unsigned long sa_flags; __sigrestore_t sa_restorer; }; // 信号处理结构 struct sigaction { // 信号处理函数 __sighandler_t sa_handler; // 标志 unsigned long sa_flags; // 信号恢复函数 __sigrestore_t sa_restorer; // 信号集 sigset_t sa_mask; /* mask last for extensibility */ }; // 另一个定义 struct k_sigaction { struct sigaction sa; }; 2.2 信号信息结构定义 用于发送信号 /* include/asm-generic/siginfo.h */ typedef struct siginfo { int si_signo; int si_errno; int si_code; union { int _pad[SI_PAD_SIZE]; /* kill() */ struct { pid_t _pid; /* sender's pid */ __ARCH_SI_UID_T _uid; /* sender's uid */ } _kill; /* POSIX.1b timers */ struct { timer_t _tid; /* timer id */ int _overrun; /* overrun count */ char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)]; sigval_t _sigval; /* same as below */ int _sys_private; /* not to be passed to user */ } _timer; /* POSIX.1b signals */ struct { pid_t _pid; /* sender's pid */ __ARCH_SI_UID_T _uid; /* sender's uid */ sigval_t _sigval; } _rt; /* SIGCHLD */ struct { pid_t _pid; /* which child */ __ARCH_SI_UID_T _uid; /* sender's uid */ int _status; /* exit code */ clock_t _utime; clock_t _stime; } _sigchld; /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ struct { void __user *_addr; /* faulting insn/memory ref. */ #ifdef __ARCH_SI_TRAPNO int _trapno; /* TRAP # which caused the signal */ #endif } _sigfault; /* SIGPOLL */ struct { __ARCH_SI_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */ int _fd; } _sigpoll; } _sifields; } siginfo_t; 3. 定义信号处理函数 signal系统调用在内核中对应的是sys_signal,sigaction对应的是sys_sysaction: /* kernel/signal.c */ /* * For backwards compatibility. Functionality superseded by sigaction. */ // signal函数已经只是为了后向兼容了,以后尽量还是使用sigaction实现为好 asmlinkage unsigned long sys_signal(int sig, __sighandler_t handler) { struct k_sigaction new_sa, old_sa; int ret; // 填写新的信号处理结构参数 // 最重要的是handler参数 new_sa.sa.sa_handler = handler; new_sa.sa.sa_flags = SA_ONESHOT | SA_NOMASK; sigemptyset(&new_sa.sa.sa_mask); // 进入do_sigaction函数处理 ret = do_sigaction(sig, &new_sa, &old_sa); // 如果返回值为0(成功), 返回原来的信号处理函数 return ret ? ret : (unsigned long)old_sa.sa.sa_handler; } /* arch/i386/kernel/signal.c */ // 注意输入的是老的信号处理结构 asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act, struct old_sigaction __user *oact) { struct k_sigaction new_ka, old_ka; int ret; // act相当于新的信号处理结构定义 if (act) { // 从用户层空间拷贝信号处理结构参数 old_sigset_t mask; if (!access_ok(VERIFY_READ, act, sizeof(*act)) || __get_user(new_ka.sa.sa_handler, &act->sa_handler) || __get_user(new_ka.sa