信号
信号的机制:
A给B发送信号,B收到信号之前执行自己的代码,收到信号后,不管执行到程序的什么位置,都要暂停运行,去处理信号,处理完毕再继续执行。与硬件中断类似——异步模式。但信号是软件层面上实现的中断,早期常被称为“软中断”。
信号的特质:
由于信号是通过软件方法实现,其实现手段导致信号有很强的延时性。但对于用户来说,这个延迟时间非常短,不易察觉。
每个进程收到的所有信号,都是由内核负责发送的,内核处理。
信号的类型
SIGHUP —— 进程session leader退出时,同session的其他进程会收到这个信号
SIGINT —— Ctrl+C
SIGQUIT —— C Ctrl+D
SIGILL —— C 非法指令
SIGABRT —— C 调用abort函数产生的信号
SIGFPE —— C 浮点异常
SIGKILL —— Kill信号
SIGSEGV —— C 无效的内存引用
SIGPIPE —— 管道破裂: 写一个没有读端口的管道
SIGALRM —— 由alarm(2)发出的信号
SIGTERM —— 终止信号
SIGUSR1 —— 用户自定义信号1
SIGUSR2 —— 用户自定义信号2
SIGCHLD —— 子进程状态变化会给父进程发送SIGCHLD信号
SIGCONT —— 进程继续(曾被停止的进程)
SIGSTOP —— 暂停进程
SIGTSTP —— 控制终端(tty)上按下停止键
SIGTTIN —— 后台进程企图从控制终端读
SIGTTOU —— 后台进程企图从控制终端写
kill - l 可以查看所有信号
[1,31]信号为常规信号+不可靠信号,[34,64]称为实时信号
信号产生函数
unsigned int alarm(unsigned int seconds)
指定seconds后,内核会给当前进程发送SIGALRM信号
返回0或剩余的描述
每个进程有且只有一个定时器
int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value)
- which指定定时方式,①自然定时:ITIMER_REAL -> SIGLARM信号;②虚拟空间计时: ITIMER_VIRTUAL-> SIGVTALRM信号(只计算进程占用cpu的时间);③运行时计时: ITIMER_PROF -> SIGPROF(计算占用cpu及执行系统调用的时间)
可代替alarm函数,精度微秒,可以实现周期定时
信号集操作函数
sigset_t set; //定义一个信号集
int sigemptyset(sigset_t *set); //将某个信号集清0 成功:0;失败:-1
int sigfillset(sigset_t *set); //将某个信号集置1 成功:0;失败:-1
int sigaddset(sigset_t *set, int signum); //将某个信号加入信号集 成功:0;失败:-1
int sigdelset(sigset_t *set, int signum); //将某个信号清出信号集 成功:0;失败:-1
int sigismember(const sigset_t *set, int signum); //判断某个信号是否在信号集中 返回值:在集合:1;不在:0;出错:-1
sigprocmask函数
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
how
- SIG_BLOCK: 屏蔽set内信号
- SIG_UNBLOCK:接触屏蔽set内的信号
- SIG_SETMASK: 用set代替原始屏蔽
set 传入参数,是一个位图,32位表示前32个信号集,set中哪个位置为1则表示当前进程屏蔽哪个信号
oldset 传出参数,保存旧的信号屏蔽集
sigpending函数
int sigpending(sigset_t *set);
读取当前进程的未决信号集,通过set传出
信号捕捉
signal函数
void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler/*回调*/);
sigaction函数
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
//act: 传入参数,新的处理方式;
//oldact: 传出参数,旧的处理方式;
struct sigaction结构体
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};
sa_handler: 指定信号捕捉后的处理函数。可赋值SIG_IGN表示忽略,SIG_DFL表示执行默认动作
sa_mask: 用信号集处理函数初始化,调用sigaction函数时表示所要屏蔽的信号集合。只在处理函数被调用期间屏蔽,调用完后失效
sa_flags :
SA_INTERRUPT 由此信号中断的系统调用不会自动重启
SA_RESTART 由此信号中断的系统调用会自动重启
SA_SIGINFO 提供附加信息,一个指向siginfo结构的指针以及一个指向进程上下文标识符的指针sa_sigaction: 当sa_flags被指定为SA_SIGINFO时才使用该信号处理程序
sa_restorer: 弃用
sigqueue函数
int sigqueue(pid_t pid, int sig, const union sigval value);
union sigval {
int sival_int; //携带int值
void *sival_ptr; //携带指针
};
向指定进程发送指定信号的同时,携带数据。
如果传地址需注意,不同进程之间的虚拟地址空间相互独立,传递当前进程地址没有作用
pause函数
int pause(void); //返回-1 并设置errno为EINTR
如果信号默认处理终止进程,则pause没有机会返回
如果信号默认处理忽略,进程继续挂起,pause不会返回
如果信号默认捕捉,则正常返回
如果信号pause收到的信号被屏蔽,则pause不能被唤醒