Linux探秘坊-------14.信号
1.预备知识
2.信号的产生
例如如果我们想要把一个进程给终止掉,那么我们就可以使用ctrl+c来终止进程,ctrl+c就是一个信号
如何更改处理型号的方式呢?
void handlerSig(int sig)//重新修改处理信号的方式
{std::cout << "获得了一个信号: " << sig << std::endl;
}//函数调用
signal(2, handlerSig);//2就是ctrl+c对应的信号,handlersig是函数指针
3.进程分类
4.信号创建方式--------系统调用----以kill函数为例
ctrl+c是直接从键盘上输入的信号,我们也可以自己写一个系统调用–mykill来实现一样的效果
mykill.cc:
#include <iostream>
#include <string>
#include <sys/types.h>
#include <signal.h>// ./mykill signumber pid
int main(int argc, char *argv[])//编译完成后,bash进程运行指令./mykill 9 1234
{if(argc != 3)//表示指令个数,:1../mykill 2.9 3.1234--进程pid{std::cout << "./mykill signumber pid" << std::endl;return 1;}int signum = std::stoi(argv[1]);//argv【1】存储指令:9 pid_t target = std::stoi(argv[2]);//argv【2】存储指令: 1234--进程pid
//二者都要使用stoi函数转换成征整形!!!!!int n = kill(target, signum);//调用kill函数,参数是进程pid和信号if(n == 0){std::cout << "send " << signum << " to " << target << " success.";}return 0;
}
testSig.cc:
#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>void handlerSig(int sig)
{std::cout << "获得了一个信号: " << sig << std::endl;exit(13);//在编译完运行程序后只要通过键盘输入信号,那么都改成输出,特别注意---⑨是没有办法改的,因为9号是强制杀掉进程,为了避免垃圾程序一直处于运行中,需要保留9号来及时删除程序,绝大部分的信号的原始处理方式都是终止进程
}int main()
{for(int i = 1; i < 32; i++)signal(i, handlerSig);//改写31个普通信号处理机制,这个循环只有在用户输出信号时才运行,无论用户输入什么信号,都会把其改写成输出信号编号,而不使用信号原本的功能int cnt = 0;while (true){std::cout << "hello world, " << cnt++ << " ,pid: " << getpid() << std::endl;sleep(1);}
}
makefile:
.PHONY:all
all:testsig mykilltestsig:testSig.ccg++ -o $@ $^ -std=c++11
mykill:mykill.ccg++ -o $@ $^ -std=c++11
.PHONY:clean
clean:rm -f testsig mykill
信号异常现象:
- 除0
#include <stdio.h>#include <signal.h>
void handler(int sig)
{printf("catch a sig : %d\n", sig);
}
// v1
int main()
{//signal(SIGFPE, handler); // 会跳8号错误:::8) SIGFPEsleep(1);int a = 10;a/=0;while(1);return 0;
}
- 野指针:
#include <stdio.h>
#include <signal.h>
void handler(int sig)
{printf("catch a sig : %d\n", sig);
}
int main()
{//signal(SIGSEGV, handler);sleep(1);int *p = NULL; // p被初始化为空指针(不指向任何有效内存)
*p = 100; // 试图通过空指针写入数据while(1);return 0;
}
使用系统调用alarm:
#include <iostream>
#include <unistd.h>
#include <signal.h>
int main()
{int count = 0;alarm(1);//运行一秒后给信号,直接终止进程while(true){std::cout << "count : "
<< count << std::endl;count++;}return 0;
}
运行结果:
- … …
count : 107148
count : 107149
Alarm clock
5.信号保存
在进程的pcb表中存有如下内容:
- 其中handler的第一个表示
default
----即保持指令原来的功能 - 第二个表示
ignore
------即忽略这个指令的功能
运行结果就是:
- 就算我输出了ctrl+c,但是进程
依旧没有停止
因为2号信号被忽略了!!!!
部分函数使用:
1.sigprocmask函数---------把信号对应的block表进行修改
2.sigpending函数---------把信号对应的pending表打印出来
- 因为是以位图的形式打印出来的,所以返回值是int类型