Linux 系统 —— 信号

  • 目录

    前言

    一、信号是什么?

    二、信号要素

    1.信号的名称

    2.进程对信号的响应

    三、信号相关函数

    总结



前言

        Linux系统下的信号与再win下学习stm32的中断有些相似,此文是学习完了stm32后学习Linux操作系统下的信号的一些小笔记


一、信号是什么?

1.信号是UNIX系统响应某些状况而产生的事件,进程在接收到信号时会采取相应的行动。

2.信号是因为某些错误条件而产生的,比如内存段冲突、浮点处理器错误或者非法指令等。

3.信号是在软件层次上对中断的一种模拟,所以通常把它称为是软中断。

4.这里给出硬和软中断的区别:

硬件中断(外部中断)      外部中断是指由外部设备通过硬件请求的方式产生的中断,也称为硬件中断

软件中断(内部中断)     内部中断是由CPU运行程序错误或执行内部程序调用引起的一种中断,也称为软件中断。

5.举例:

“中断”就是像从一个事件处理转而处理其他事件,处理完毕后继续处理最开始的事件。“信号\"就是属于这么一种“中断\"。我们在终端上敲\"Ctrl+c\"”,就产生一个中断\",相当于产生一个信号,接着就会处理这么一个“中断任务”(默认的处理方式为中断当前进程)。

二、信号要素

1.信号的名称

Linux 系统 —— 信号_第1张图片

Linux 系统 —— 信号_第2张图片

2.进程对信号的响应

2.1.忽略信号:不采取任何操作、有两个信号不能被忽略:SIGKILL和SIGSTOP。

注:SIGKILL和SIGSTOP这两个信号是不会被捕捉、阻塞、忽略的。

2.2.捕获并处理信号:内核中断正在执行的代码,转去执行信号的处理函数。

2.3.执行默认操作:默认操作通常是终止进程,这取决于被发送的信号。


三、信号相关函数

1.signal函数

函数原型:

__sighandler_t signal(int signum, __sighandler_t handler);

返回值:

                成功:0

                失败:-1

两个参数:

参数1:int signum ->准备捕捉或屏蔽的信号

参数2:__sighandler_t handler ->接收到指定信号时将要调用的函数

注:参数2的函数的参数必须有一个int类型的参数,即接收到的信号代码,它本身的类型是void

        handler也可以是下面两个特殊值: SIG_IGN ->屏蔽该信号; SIG_DFL ->恢复默认行为.

例:

#include
#include 
#include 
#include 
void sig_handler(int num)
{
    printf("\nrecvive the signal is %d\n", num);
}
 
int main()
{
    int time = 10;
 
    signal(SIGINT, sig_handler);//键盘键入CTRL+C产生信号
    printf("enter to the sleep.\n");
    //sleep(time);
    do{
        time = sleep(time);
    }while(time > 0);
 
    printf("sleep is over, main over.\n");
 
    exit(0);
}

2.kill函数

作用:给指定进程发送指定信号

格式:kill -signum pid

返回值:

                成功:0

                失败:-1

3.raise函数

作用:给自己发送信号,raise(sig)等价于kill(getpid(), sig);

返回值:

                成功:0

                失败:-1

例:

#include
#include
#include

void signal_catchfunc(int);


int main() {

   int ret;

   signal(SIGINT, signal_catchfunc);

   printf("开始生成一个信号\n");
   ret = raise(SIGINT);//产生一个信号,成功返回0
   if (ret != 0) {
      printf("错误,不能生成SIGINT信号\n");
      exit(0);//强制退出
}
printf("退出....\n");
   return 0;
}

void signal_catchfunc(int signal) {
   printf("捕获信号\n");
}

4.pause函数

作用:使进程挂起,直到一个信号被捕获

返回值:-1

例:

//#include 
#include   // 关于信号的头文件
#include 
#include 
#include 
//using namespace std;

void sighandler1(int signum)
{
   printf("捕获信号 %d,跳出...\n", signum);
  
}

int main()
{
    signal(SIGINT,sighandler1);    
    sleep(2);
    printf("before pause\r\n");
    pause();//pause使调用者进程挂起,直到一个信号被捕获
    printf("after pause\r\n");
}

在程序执行到pause()时,进程挂起,不往下进行,直到有信号进来,才会继续执行

5.sigaction函数

作用:sigaction函数用于改变进程接收到特定信号后的行为。

原型:

int  sigaction(int signum,const struct sigaction *act,const struct sigaction *old);

参数:

参数1:信号的值,可以为除SIGKILL及SIGSTOP外的任何一 个特定有效的信号(为这两个信号定义自己的处理函数,将导致信号安装错误)

参数2:指向结构sigaction的一个实例的指针,指定对特定信号的处理,可以为空,进程会以缺省方式对信号处理

参数3:指向的对象用来保存原来对相应信号的处理,可指定oldact为NULL

注:第二个参数尤为重要:

包含了对指定信号的处理信号所传递的信息信号处理函数执行过程中应屏蔽掉哪些函数等等

返回值:

                成功:0

                失败:-1

部分代码示例:

static void sig_usr(int signum)
{
    if(signum == SIGUSR1)
    {
        printf("SIGUSR1 received\n");
    }
    else if(signum == SIGUSR2)
    {
        printf("SIGUSR2 received\n");
    }
    else
    {
        printf("signal %d received\n", signum);
    }
}

/*此处省略多行代码*/

    struct sigaction sa_usr;
    sa_usr.sa_flags = 0;
    sa_usr.sa_handler = sig_usr;   //信号处理函数
    
    sigaction(SIGUSR1, &sa_usr, NULL);
    sigaction(SIGUSR2, &sa_usr, NULL);

6.setitimer函数:

作用:定时器

原型:

int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue));

参数:

参数1:指定定时器类型

        ITIMER_REAL:经过指定的时间后,内核将发送SIGALRM信号给本进程

        ITIMER_VIRTUAL :程序在用户空间执行指定的时间后,内核将发送SIGVTALRM信号给本进程

        ITIMER_PROF :进程在内核空间中执行时,时间计数会减少,通常与ITIMER_VIRTUAL共用,代表进程在用户空间与内核空间中运行指定时间后,内核将发送SIGPROF信号给本进程

返回值:

                成功:0

                失败:-1

例:

#include 
#include 
#include 
#include 


#define COUNT_SEC 1
#define COUNT_USEC 0
#define COUNT_SEC1 3

static void Timer_Test(int sig)
{
    printf("This is a Test\n");
}

/*Initialize timer*/
static void Init_timer(struct itimerval *tick)
{
    int ret;
    memset(tick, 0, sizeof(struct itimerval));
/*    
it_value为计时时长,it_interval为定时器的间隔,即第一次计时
it_value时长发送信号,再往后的信号每隔一个it_interval发送一次
 */
    /*initialize it_value*/
    //定时时间
    tick->it_value.tv_sec = COUNT_SEC;     
    tick->it_value.tv_usec = COUNT_USEC;

    /*initialize it_interval*/
    //间隔
    tick->it_interval.tv_sec = COUNT_SEC;    
    tick->it_interval.tv_usec = COUNT_USEC;

}

int main(int argc, const char * argv [])
{
    int ret = 0;
    struct itimerval tick;

    signal(SIGALRM, Timer_Test);//接收到定时器产生的SIGALRM信号后,执行Timer_Test()函数

    Init_timer(&tick);

    ret = setitimer(ITIMER_REAL, &tick, NULL);//ITIMER_REAL:经过指定的时间后,内核将发送SIGALRM信号给本进程
    if(ret < 0)
    {
        perror("setitimer");
        return -1;
    }
    for (;;);  //此处循环使主函数不结束。主函数结束后定时函数也将结束。

    return 0;
}

总结

        小笔记

        参考:http://t.csdn.cn/vI4SVhttp://t.csdn.cn/vI4SV

你可能感兴趣的:(linux操作系统,linux)