信号:通知进程产生了某个事件。
一. signal:改变信号的响应方式 默认:SIG_IGN 默认:SIG_DFL
自定义方法:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>//fork,wait
#include<signal.h>//signal函数
#include<fcntl.h>//open read
void fun(int sig)//自定义类型是typedef void(*sighandle_t)(int)即类型名改为sighandle_t 返回为void类型,形参为Int类型
{
printf("sid=%d\n",sig);
}
int main()
{
signal(SIGINT,fun);//自定义 当运行SIDINT即ctrl+c 时,不进行退出而是进行自己定义的fun函数
while(1)
{
printf("hello pid=%d",getpid());
sleep(1);
}
}
忽略信号方法:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>//fork,wait
#include<signal.h>//signal函数
#include<fcntl.h>//open read
void fun(int sig)//自定义类型是typedef void(*sighandle_t)(int)即类型名改为sighandle_t 返回为void类型,形参为Int类型
{
printf("sid=%d\n",sig);
}
int main()
{
signal(SIGINT,SIG_IGN);//SIG_IGN表示忽略信号ctrl+c 这一行放在最上边
//signal(SIGINT,fun);//自定义 当运行SIDINT即ctrl+c 时,不进行退出而是进行自己定义的fun函数
while(1)
{
printf("hello pid=%d",getpid());
sleep(1);
}
}
第一次自定义,第二次恢复默认:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>//fork,wait
#include<signal.h>//signal函数
#include<fcntl.h>//open read
void fun(int sig)//自定义类型是typedef void(*sighandle_t)(int)即类型名改为sighandle_t 返回为void类型,形参为Int类型
{
printf("sid=%d\n",sig);
signal(sig,SIG_DFL);//sig跟SIGINT是一样的,SIG_DFL表示恢复默认
}
int main()
{
//signal(SIGINT,SIG_IGN);//SIG_IGN表示忽略信号ctrl+c
signal(SIGINT,fun);//自定义 当运行SIDINT即ctrl+c 时,不进行退出而是进行自己定义的fun函数
while(1)
{
printf("hello pid=%d",getpid());
sleep(1);
}
}
二. kill: 发送信号 int kill(pid_t pid,int sig):pid为给哪个进程发,那个进程的id号 sig为给这个进程发什么信号
头文件#include<signal.h> 返回值为-1是失败
用户在键盘上输入要结束的id号,输入将要发送的信号的代号:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>//fork,wait
#include<signal.h>//signal函数
#include<fcntl.h>//open read
int main(int argc,char*argv[])
{
if(argc!=3)
{
printf("argc err\n");
exit(1);
}
sscanf(argv[1],"%d",&pid);//sscanf与atoi是一样的都是将char*转变为int类型
sscanf(argv[2],"%d",&sig);
//int pid=atoi(argv[1]);//argv在定义中为char*类型,但在kill中要为Int类型,顾用atoi将字符改为字符串
int sig=atoi(argv[2]);
if(kill(pid,sig)==-1)
{
printf("kill err\n");
exit(1);
}
}
注意:改代码在使用时需要与上面的 第一次自定义,第二次恢复默认 一起使用:
三. 解决僵死进程用信号处理不会阻塞住父进程代码如下:
#include<stdio.h>//测试fork进程
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/wait.h>
#include<signal.h>//signal的头文件
void fun(int sig)
{
printf("sig=%d\n",sig);
wait(NULL);//不会卡住父进程但也会解决僵死进程
}
int main()
{
int n=0;
char *s=NULL;
signal(SIGCHLD,fun);//SIGCHLD是子进程结束后,会默认给父进程发生该信号
pid_t pid=fork();
if(pid==-1)
{
exit(1);
}
if(pid==0)
{
n=3;
s="child";
}
else
{
n=7;
s="parent";
}
for(int i=0;i<n;i++)
{
printf("s=%s curr_pid=%d ppid=%d n=%d n=%p\n",s,getpid(),getppid(),n,&n);//当前进程的id号,getpid()为获取id号,ppid为其父进程id号
sleep(1);
}
exit(0);
}
四.非法内存访问:SIGSEGV
#include<stdio.h>//测试fork进程
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/wait.h>
#include<signal.h>//signal的头文件
void fun(int sig)
{
printf("sig=%d\n",sig);
}
int main()
{
signal(SIGSEGV,fun);//若出现非法访问内存,则响应改为fun
char arr[]="abcde";//常量不能改变值
arr[1]='c';//err属于非法访问
printf("fun nb");
}