linux_unix编程手册-信号概述signal函数

本文深入探讨了Linux系统中信号处理的基础知识,包括signal()和sigaction()函数的使用,以及如何通过pause()函数等待信号。文章提供了代码示例,展示了如何为SIGINT和SIGQUIT信号设置相同的处理程序。

关于linux_unix编程手册的代码见
https://github.com/zzu-andrew/linux_unix.git
上面由编译过得代码可以直接使用或者自己clone之后再使用

在这里插入图片描述
加粗样式

在这里插入图片描述

在这里插入图片描述

改变信号量的处置

在这里插入图片描述
加粗样式
在linux手册中对函数signal的解释是:

 #include <signal.h>

 typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

可以看出man手册对signal的书写更加的形象,signal返回的是一个 void (*sighandler_t)(int)类型的函数
返回的函数就是之前的信号处理函数,一般使用signal的过程如下:
在这里插入图片描述

/*************************************************************************\
*                  Copyright (C) Michael Kerrisk, 2018.                   *
*                                                                         *
* This program is free software. You may use, modify, and redistribute it *
* under the terms of the GNU General Public License as published by the   *
* Free Software Foundation, either version 3 or (at your option) any      *
* later version. This program is distributed without any warranty.  See   *
* the file COPYING.gpl-v3 for details.                                    *
\*************************************************************************/

/* Listing 20-1 */

/* ouch.c

   Catch the SIGINT signal, generated by typing control-C (^C).

   Note that although we use signal() to establish the signal handler in this
   program, the use of sigaction() is always preferable for this task.
*/
#include <signal.h>
#include "tlpi_hdr.h"

static void
sigHandler(int sig)
{
    printf("Ouch!\n");                  /* UNSAFE (see Section 21.1.2) */
}

int
main(int argc, char *argv[])
{
    int j;

    /* Establish handler for SIGINT. Here we use the simpler signal()
       API to establish a signal handler, but for the reasons described in
       Section 22.7 of TLPI, sigaction() is the (strongly) preferred API
       for this task. */

    if (signal(SIGINT, sigHandler) == SIG_ERR)
        errExit("signal");

    /* Loop continuously waiting for signals to be delivered */

    for (j = 0; ; j++) {
        printf("%d\n", j);
          //加上,不然程序不会自己退出,并且使用  ^C  ^D他也不能使程序退出
        if(j  == 20)
        {
            exit(0);
        }
        sleep(3);                       /* Loop slowly... */
    }
}

程序测试过程:
在这里插入图片描述

说明,程序中信号处理函数使用printf()函数显示具体信息,但是在现实的编程环境中是绝对不允许在信号处理函数中使用stdio函数,这里只是将其作为调试的一种手段

为两个不同的信号建立同样的信号处理程序:

/*************************************************************************\
*                  Copyright (C) Michael Kerrisk, 2018.                   *
*                                                                         *
* This program is free software. You may use, modify, and redistribute it *
* under the terms of the GNU General Public License as published by the   *
* Free Software Foundation, either version 3 or (at your option) any      *
* later version. This program is distributed without any warranty.  See   *
* the file COPYING.gpl-v3 for details.                                    *
\*************************************************************************/

/* Listing 20-2 */

/* intquit.c

   Catch the SIGINT and SIGQUIT signals, which are normally generated
   by the control-C (^C) and control-\ (^\) keys respectively.

   Note that although we use signal() to establish signal handlers in this
   program, the use of sigaction() is always preferable for this task.
*/
#include <signal.h>
#include "tlpi_hdr.h"

static void
sigHandler(int sig)
{
    static int count = 0;

    /* UNSAFE: This handler uses non-async-signal-safe functions
       (printf(), exit(); see Section 21.1.2) */

    if (sig == SIGINT) {
        count++;
        printf("Caught SIGINT (%d)\n", count);
        return;                 /* Resume execution at point of interruption */
    }

    /* Must be SIGQUIT - print a message and terminate the process */

    printf("Caught SIGQUIT - that's all folks!\n");
    exit(EXIT_SUCCESS);
}

int
main(int argc, char *argv[])
{
    /* Establish same handler for SIGINT and SIGQUIT. Here we use the
       simpler signal() API to establish a signal handler, but for the
       reasons described in Section 22.7 of TLPI, sigaction() is the
       (strongly) preferred API for this task. */

    if (signal(SIGINT, sigHandler) == SIG_ERR)
        errExit("signal");
    if (signal(SIGQUIT, sigHandler) == SIG_ERR)
        errExit("signal");

    for (;;)                    /* Loop forever, waiting for signals */
        pause();                /* Block until a signal is caught */
}

发送信号,使用kill一个进程可以向另一个进程发送信号(之所以使用kill作为术语,是因为早期的UNIX实现中大多数信号的默认行为是终止进程)

#include <signal.h>

int kill(pid_t pid, int sig);

pid参数用于标示一个或者多个目标进程,而sig则指向要发送的信号
在这里插入图片描述

kill()系统调用还有另一重功用,将参数sig指定为0(即所谓的空信号),则无信号发送,相反kill()仅会检查错误检验,查看是否可以向目标进程发送信号,从另一个角度这意味着,可以使用控信号检测具有特定进程ID的进程是否存在。若是发送信号失败,且errno为ESRCH,则表明目标进程不存在,若果调用失败且errno为EPERM(表示进程存在但是无权向目标进程发送信号)或者调用成功(有权向目标进程发送信号),那么就表示进程存在。
在这里插入图片描述
在这里插入图片描述

改变信号处置:sigaction()函数

除去signal()之外,sigaction()系统调用是设置信号好处置的另一个选择;
在这里插入图片描述
在这里插入图片描述

等待信号:pause()

调用pause()将暂停进程的执行,直至信号处理器函数中断该调用为止(或者直至一个为处理的信号终止进程为止)。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

andrewbytecoder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值