Linux信号基本概念

发布于:2022-10-17 ⋅ 阅读:(564) ⋅ 点赞:(0)

信号是系统响应某个条件而产生的事件,进程接收到信号号会执行相应的操作;

与信号有关的系统调用在<signal.h>头文件中。

1、信号的存储位置

vim /usr/include/x86_64-linux-gnu/bits/signum.h

2、常见信号的值,即对应的功能说明

信号名称 说明
SIGABORT *进程异常终止

SIGALRM

超时警告
SIGFPE *浮点运算符异常
SIGHUP 连接挂断
SIGILL *非法指令
SIGINT 终端中断
SIGKILL 终止进程(此信号不能被捕获或忽略)
SIGPIPE 向无读进程的管道写数据
SIGQUIT 终端退出
SIGSEGV *无效内存段访问
SIGTERM 终止
SIGUSR1 用户定义信号1
SIGUSR2 用户定义信号2

3、信号的值在系统源码中的定义

#define  信号名称  信号代号

#define  SIGHUP  1
#define  SIGINT  2 //键盘按下 Ctrl+c 时,会产生终端中断信号
#define  SIGQUIT  3//键盘按下 Ctrl+\ 时,会产生终端退出信号
#define  SIGILL  4
#define  SIGTRAP  5
#define  SIGABRT  6
#define SIGIOT  6
#define  SIGBUS  7
#define  SIGFPE  8
#define  SIGKILL  9 //该信号的响应方式不允许改变
#define  SIGUSR1  10
#define  SIGSEGV  11
#define  SIGUSR2  12
#define  SIGPIPE  13 //读端关闭的描述符,写端写入时产生,该信号会终止程序(向
无读进程的管道写数据)

#define  SIGALRM  14
#define  SIGTERM  15 //系统 kill 命令默认发送的信号
#define  SIGSTKFLT  16
#define  SIGCHLD  17 //子进程结束后,会默认给父进程发送该信号
#define  SIGCONT  18
#define  SIGSTOP  19
#define  SIGTSTP  20
#define  SIGTTIN  21
#define  SIGTTOU  22
#define  SIGURG  23

4、响应方式

三种响应方式:默认,忽略,自定义。

设置信号的响应方式:通过函数signal()

man  signal:

默认:SIG_DFL;

忽略:SIG_IGN;

自定义:void  fun_sig(int  sig);

(1)默认响应方式

正常是默认,代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
int main()
{
while(1)
{
printf("main run\n");
sleep(1);
}
exit(0);
}

(2)自定义响应方式

通过signal系统调用更改信号的响应方式:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <signal.h>
void sig_fun(int sig)
{
printf("sig=%d\n",sig);
}
int main()
{
signal(SIGINT,sig_fun);//回调函数
while(1)
{
printf("main run\n");
sleep(1);
}
exit(0);
}

(3)忽略

SIG_IGN

signal(SIGINT,SIG_IGN);

(4)扩展练习

 收到SIGINT信号,第一次打印信号的代号,第二次按照默认方式把进程结束;

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <signal.h>
void sig_fun(int sig)
{
printf("sig=%d\n",sig);
signal(sig,SIG_DFL);
}
int main()
{
signal(SIGINT,sig_fun);
//signal(SIGINT,SIG_IGN);
while(1)
{
printf("main run\n");
sleep(1);
}
exit(0);
}

(5)实现kill命令

man 2 kill:系统调用

向pid进程发送sig信号;返回值-1表示失败,0表示成功

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<signal.h>
#include<unistd.h>
#include <errno.h>


int main(int argc,char *argv[])
{
   if(argc!=3)
   {   
       printf("argc error\n");
       return -1; 
   }   
   int pid=0;
   int sig=0;

   sscanf(argv[1],"%d",&pid);
   sscanf(argv[2],"%d",&sig);

   if(kill(pid,sig)==-1)
   {   
       perror("kill error\n");
   }
   exit(0);
}

5、SIGCHLD信号

子进程结束,父进程会收到内核发送的SIGCHLD信号;;

(1)验证信号

改变SIGCHLD信号的响应方式

(2)处理僵死进程(wait结合信号)

include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
#include<sys/wait.h>

void fun(int sig)
{
    printf("sig=%d\n",sig);
   int val=0;
   int id=wait(&val);
}

int main()
{
    int n=0;
    char *s=NULL;
    pid_t pid=fork();
    if(pid==-1)
    {   
        printf("fork error\n");
        exit(1);
    }
    if(pid ==0)
    {
        n=3;
        s="child";
    }
    else
    {
        signal(SIGCHLD,fun);
        n=7;
        s="parent";
    }
    for(int i=0;i<n;i++)
    {
        printf("s=%s\n",s);
        sleep(1);
    }
    exit(0);
}

网站公告

今日签到

点亮在社区的每一天
去签到