信号的产生
进程信号:
信号生命周期:信号的产生—>信号的注册—>信号的阻塞(屏蔽)—>信号的注销—>信号的处理
信号列表:知道有哪些信号,并且对应了哪些操作
kill :可以杀死一个进程,但并不是为了杀死一个进程设计的,而是为了给某一指定进程发送一个信号
kill杀死进程的时候,默认给这个进程发送的是哪个信号?
在默认情况下,采用编号为15的TERM信号。TERM信号将终止所有不能捕获该信号的进程。对于那些可以捕获该信号的进程就要用编号为9的kill信号,强行“杀掉”该进程。
Linux下一共有62个信号(32,33没有),并且分了两类:1-31 是非可靠信号(非实时信号):1-31号信号是继承于unix而来,每一个信号 都对应了一个指定事件;非可靠是指信号有可能丢失,如果有相同的信号已经注册到这个进程没有被处理,那么接下来相同信号就会丢掉;
34-64 是可靠信号(实时信号):信号不会丢失。
信号的功能:实际上就是为了通知进程发生了哪些事件,应该怎么处理,信号实际也可以归为一类进程间通信。
中断:打断当前操作,然后去处理这个中断的事件
硬件中断:ctrl+c(中断前台进程)或者ctrl+\(退出前台进程)
软件中断:linux下的信号实际是软中断
信号与信号量区别:
信号实际是一个软中断,用于通知进程发生了某些事件,实际信号也可以算作进程间通信的方式之一。因为可以在一个进程通过给另一个进程发生信号,来告诉另一个进程发生了什么事。
产生信号:
1.硬件中断(ctrl+C),对于进程来说是软中断;
#include<stdio.h>
#include<unistd.h>
int main()
{
while(1)
{
printf("pick\n");
sleep(1);
}
return 0;
}
crtl+c是硬件中断,操作系统就会让前台进程退出,相当于2号信号SIGINT;
前台进程是一直运行在终端上,如果终端有进程正在运行,按命令没反应
后台进程:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
if(fork()>0)
{
exit(0);
}
while(1)
{
printf("pick\n");
sleep(1);
}
return 0;
}
在后台进程中输入ls等命令有效,但是ctrl+c不能使进程结束,需要用kill命令使进程退出。
2.硬件异常 (段错误:内存访问错误SIGSEGV);
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char *ptr=NULL;
memcpy(ptr,"hello",10);
return 0;
}
段错误是11号信号SIGSSEGV。
3.接口调用发送信号 (kill命令);
kill可以杀死一个进程,但并不是为了杀死一个进程设计的,而是为了给某一指定进程发送一个信号。
4.软件条件产生(kill函数、raise函数、alarm函数、sigqueue函数);
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<signal.h>
int main()
{
kill(getpid(),SIGINT); ///给自己发送SIGINT中断信号
while(1)
{
printf("pick\n");
sleep(3);
}
return 0;
}
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<signal.h>
int main()
{
raise(SIGABRT);//给自己发送SIGABRT信号
while(1)
{
printf("pick\n");
sleep(3);
}
return 0;
}
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<signal.h>
int main()
{
sigqueue(getpid(),SIGPIPE,(union sigval)0);
while(1)
{
printf("pick\n");
sleep(3);
}
return 0;
}
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>
int main(){
int ret=alarm(5);//ret=0
sleep(1);//睡了一秒
ret=alarm(3);//返回上一个定时器剩余时间,由于睡了一秒还剩4秒 printf("ret:%d\n",ret);
while(1)
{
sleep(1);
}
return 0;
}
Core Dump(核心转储)
- 程序异常的时候会记录一个核心转储文件,在这个文件中记录的是程序的运行数据。当一个程序异常崩溃时,而这个错误可能只是偶尔发生,那么这种错误将非常难定位,因为我们也不知道到底什么时候才会崩溃。因此这个转储文件就十分重要,因为它可以帮我们使用gdb调试查看,定位错误。
- gdb运行可执行程序,然后在gdb中使用命令:core -file +转储文件名称(如core.3996)来加载程序的运行数据,然后可以定位错误。
- 但是程序的核心转储功能默认是关闭的,转储文件大小默认是0,因为运行数据中可能会有安全性信息,以及文件增多会占用资源。
- 查看转储文件大小或设置:
ulimit -c (查看);
ulimit -c size (通过设置转储文件大小来开启转储功能)
上一篇: 信号的产生
下一篇: Linux信号的有关概念及使用