Linux日常——信号(signal)

信号是UNIX和Linux系统响应某些条件而产生的一个事件,接收到该信号的进程会相应地采取一些行动。

关于信号我们需要了解以下4点:
1、关于进程,如果收到一个信号,它可以识别信号,也知道如何处理该信号。
2、关于处理信号的时机,当一个进程收到一个信号时,它并不会立即处理信号,而是先记下这个信号。(因为此时进程有可能出于不适合处理信号的时机)
3、对于系统而言,它将信号写入它要发送信号的进程的PCB块的信号字段–>该行为表示系统发送了信号。
4、对于进程而言,它的PCB块的信号字段被修改–>该行为表示进程收到了信号。
操作系统是进程的管理者,所以它可以向进程发送信息。

PCB的信号字段–位图
结构描述:信号量只需要知道它收到还是未收到,所以使用位图是非常适合的
–一个bit位表示一个信号
–0/1表示是否收到信号
信号与进程是异步关系的,信号可以在进程生命周期的任何时候产生。

信号量
这里写图片描述
1-31:普通信号(收到信号后不立即处理)
34-64:实时信号(具有时效性,进程收到信号后立即执行)

进程放在前台,shell命令无法执行,可用ctrl+c终止进程
进程放在后台(命令后面加&),ctrl+c无法执行
组合键(ctrl+c/ctrl+z…)只能操作前台进程,操作 系统将其解释为信号。
mysig.c是一个死循环,以下是分别让它在前台和后台执行时的情况。

int main()
{
    while (1);
    return 0;
}

前台执行:
这里写图片描述
后台执行:
这里写图片描述

信号产生

  1. 键盘输入
  2. kill命令
  3. 软硬件异常
    硬件异常:除0操作、指针异常
    除0操作:
    int a=10;
    a/=0;
    这里写图片描述
    发送8号信号(SIGFPE)
    指针异常:
    int* p=(int*)9;//p指向地址为10的位置
    *p=9;
    这里写图片描述
    发送11号信号(SIGSEGV)段异常

core dump<核心转储>

当进程异常退出时,操作系统将内存中的进程调试信息转储到硬盘上。
操作系统在进程收到某些信号而终止运行时,将此时进程地址空间的内容以及有关进程状态的其他信息写出的一个磁盘文件。这种信息往往用于调试。
系统一般禁止生成core file,防止因生成过多的文件占用过多的硬盘位置,导致服务器挂掉。
查看core file
这里写图片描述
修改大小
在使用gdb之前,在编译是要加-g选项
接着查看生成的core文件名[core.pid]
这里写图片描述
使用gdb进行查看core file
gdb 可执行文件名 corefile_name
这里写图片描述
可知错误为第25行,指针错误。

发送信号的函数:
int kill(pid_t pid, int sig);
用于向任何进程组或进程发送任何信号。
头文件
include

#include<stdio.h>
#include<sys/types.h>
#include<signal.h>
#include<stdlib.h>
static void usage(char* filename)
{
    printf("./%s signum pid\n",filename);
}
int main(int argc,char* argv[])
{
    if(argc!=3)
    {
        usage(argv[0]);
    }
    int sig=atoi(argv[1]);
    pid_t id=atoi(argv[2]);
    kill(id,sig);
    return 0;
}

test.c

int main()
{
   while(1);
}

这里写图片描述
这里写图片描述
int raise(int sig)
用于向自己发送任何信号。
头文件
include

#include<stdio.h>
#include<sys/types.h>
#include<signal.h>
void handler(int sig)
{
    printf("get a sig %d\n",sig);
}

int main()
{
    signal(2,handler);
    while(1)
    {
    //每隔一秒发一个2号信号
        sleep(1);
        raise(2);
    }
}

这里写图片描述

信号处理

处理动作有以下三种:
1. 忽略此信号。
2. 执⾏行该信号的默认处理动作。
3. 提供⼀一个信号处理函数,要求内核在处理该信号时切换到⽤用户态执⾏行这个处理函数,这种方式称为捕捉(catch)⼀一个信号。

信号捕捉–修改信号默认行为的动作

头文件:signal.h
函数:signal
typedef void (*sighandler_t)(int)
sighandler_t signal(int signum, sighandler_t handler);

mysig.c
#include<stdio.h>
#include<signal.h>
void sighand(int sig)
{
    printf("get a sig is %d\n",sig);
}
int main()
{
    int i=0;
    for(;i<=31;++i)
    {
        signal(i,sighand);
    }

    while(1);
    return 0;
}

运行结果:
这里写图片描述
此时进程将一直处于死循环,并不会因为键盘信号而终止,因为程序中已经将所有的信号都重新进行了设置,结束这个进程可以使用kill命令发送9号信号。
9号命令:一个很强势的信号,像霸道总裁一样,不会被屏蔽,不会被修改。
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值