首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Linux探秘坊-------14.信号

Linux探秘坊-------14.信号

作者头像
hope kc
发布2025-07-18 08:45:39
发布2025-07-18 08:45:39
9200
代码可运行
举报
文章被收录于专栏:学习学习
运行总次数:0
代码可运行

1.预备知识

2.信号的产生

例如如果我们想要把一个进程给终止掉,那么我们就可以使用ctrl+c来终止进程,ctrl+c就是一个信号

如何更改处理型号的方式呢?

代码语言:javascript
代码运行次数:0
运行
复制
void handlerSig(int sig)//重新修改处理信号的方式
{
    std::cout << "获得了一个信号: " << sig << std::endl;
}


//函数调用
signal(2, handlerSig);//2就是ctrl+c对应的信号,handlersig是函数指针

3.进程分类

4.信号创建方式--------系统调用----以kill函数为例

ctrl+c是直接从键盘上输入的信号,我们也可以自己写一个系统调用–mykill来实现一样的效果

mykill.cc:

代码语言:javascript
代码运行次数:0
运行
复制
#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:

代码语言:javascript
代码运行次数:0
运行
复制
#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:

代码语言:javascript
代码运行次数:0
运行
复制
.PHONY:all
all:testsig mykill

testsig:testSig.cc
	g++ -o $@ $^ -std=c++11
mykill:mykill.cc
	g++ -o $@ $^ -std=c++11
.PHONY:clean
clean:
	rm -f testsig mykill

信号异常现象:

  • 除0
代码语言:javascript
代码运行次数: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) SIGFPE
 sleep(1);
 int a = 10;
 a/=0;
 while(1);
 return 0;
}
  • 野指针:
代码语言:javascript
代码运行次数: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:

代码语言:javascript
代码运行次数:0
运行
复制
#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类型

6.信号处理

1.信号捕捉
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-07-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.预备知识
  • 2.信号的产生
  • 3.进程分类
  • 4.信号创建方式--------系统调用----以kill函数为例
  • 5.信号保存
    • 1.sigprocmask函数---------把信号对应的block表进行修改
    • 2.sigpending函数---------把信号对应的pending表打印出来
  • 6.信号处理
    • 1.信号捕捉
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档