信号(一)
概念:
系统在响应某些状况而产生的事件,进程在接收到信号后采取相应的动作。
产生信号的方式:
1.键盘事件
Ctrl + c → 2) SIGINT(终止/中断) "INT" ----Interrupt
Ctrl + z → 20) SIGTSTP(暂停/停止) "T" ----Terminal 终端。
Ctrl + → 3) SIGQUIT(退出)
2.硬件异常产生指令
- 除0操作 → 8) SIGFPE (浮点数例外) "F" -----float 浮点数。
- 非法访问内存 → 11) SIGSEGV (段错误)
- 总线错误 → 7) SIGBUS
3.函数/命令产生信号
kill命令产生信号:kill -SIGKILL pid
kill函数:给指定进程发送指定信号
在linux中,输入 kill -l,会出现linux系统中信号的类别:
这就是信号的全部种类。其中1-31是普通信号,34以后是实时信号。
信号的处理方式:
- 忽略(SIGKILL和SIGSTOP这两个信号是不能被忽略的,因为他)
- 执行默认处理方式(缺省处理方式,由系统定义处理方式 可通过 man 7 signal查看具体)
- 捕捉并处理。(方式由用户自定义)
信号分类:
- 不可靠信号:(1-31)
Linux信号处理继承来自基于UNIX,早期的UNIX当信号处理函数执行完毕后,该信号恢复成缺省处理动作。虽然Linux已改进,但是继承开发的东西太多了,已经不可能把该恢复默认成缺省动作删除了。
- 不可靠信号:(1-31)
信号不排队。在某一时刻,几个信号传递过来的时候并没有处理完,导致了某些信号的丢失。
- 可靠信号:(34-64):不会出现信号丢失。
注册信号:
void (*signal(int signum, void(*pf)(int)))(int); void (*pf)(int); //自定义的函数处理
发送信号:
kill(pid_t pid, int signum);
pid_t说明:
-
- pid > 0:将信号传给进程识别码未pid的进程。
- pid == 0:将进程传给和目前进程相同进程组的所有进程
- pid == -1:将信号广播传送给系统内所有进程。
- pid < 0:将信号传给进程组识别码为pid绝对值的所有进程。
singnum代表信号编号,参照上方kill -l显示的信号
返回值:
执行成功则返回0,失败返回-1。
错误码:
EINVAG:参数sig不合法。
ESRCH:参数pid所指定的进程或进程组不存在。
EPERM:权限不够无法传送给指定进程。
实例一:
注册和发送信号:
/*register.c*/ #include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<signal.h> #include<sys/types.h> void handler(int s) { printf("recv %d\n", s); exit(0); } int main() { signal(SIGUSR1, handler); pid_t pid; pid = fork(); if (pid == 0) { sleep(3); kill(getppid(), SIGUSR1); //getppid()获取父进程进程号 } else { for( ; ;) { printf("1"); fflush(stdout); sleep(1); } } return 0; }
运行结果:
ubuntu@ubuntu:~/wangqinghe/signal$ ./register
1111recv 10