0
点赞
收藏
分享

微信扫一扫

STM32(十):ADC模数转换器

谁知我新 2024-09-09 阅读 31
linux

信号

什么是信号

信号是Linux提供的一种向指定进程发送特定事件的方式。

Linux中规定了64种信号,其中1到31号为不可靠信号(可能丢失),32到64号为可靠信号(不可能丢失)。

注:绝大多数的默认操作都是终止进程。 

信号取值名称作用默认操作
1SIGHUP挂起
2SIGINT中断
3SIGQUIT退出
4SIGILL非法指令
5SIGTRAP断点或陷阱指令
6SIGABRTabort发出的信号
7SIGBUS非法内存访问
8SIGFPE浮点异常
9SIGKILLkill信号不能被忽略、处理和阻塞
10SIGUSR1用户信号1
11SIGSEGV无效内存访问
12SIGUSR2用户信号2
13SIGPIPE管道破损,没有读端的管道写数据
14SIGALRMalarm发出的信号
15SIGTERM终止信号
16SIGSTKFLT栈溢出
17SIGCHLD子进程退出默认忽略
18SIGCONT进程继续
19SIGSTOP进程停止不能被忽略、处理和阻塞
20SIGTSTP进程停止
21SIGTTIN进程停止,后台进程从终端读数据时
22SIGTTOU进程停止,后台进程向终端写数据时
23SIGURGIO有紧急数据到达当前进程默认忽略
24SIGXCPU进程的CPU时间片到期
25SIGXFSZ文件大小的超出上限
26SIGVTALRM虚拟时钟超时
27SIGPROFprofile时钟超时
28SIGWINCH窗口大小改变默认忽略
29SIGIOIO相关
30SIGPWR关机默认忽略
31SIGSYS系统调用异常

        信号通常经历以下三个阶段,产生、保存、递达(处理)。处于保存时期的信号处于一个叫未决的状态。可以简单理解为信号到了,但未处理的状态。 

        举个例子,你的朋友让你给他买瓶汽水,但由于你手头上有更加重要的事,所以你默默地记下给他买瓶汽水这个信号等到你忙完后才去执行。此时你对信号的处理是阻塞,信号在被递达前都处于未决状态。当然,除了阻塞你也可以选择忽略,忽略则是信号到了但是你直接无视。

 

信号的产生

信号的产生是异步的,他能够使一个正在执行的进程被异步打断,转而去处理一个突发事件。

信号的产生大致有以下五种原因,但从始至终信号都是有OS来发送的

信号的保存与处理

每个进程都有一个对应的task_struct,而在task_struct中有一个管理信号的结构。这个结构主要分为三部分。pending、block是两张位图,pengding的每个位置都代表对应的信号,0或1代表该信号是否未决(到达但未处理)。clock的每个位置同样代表对应的信号,0或1代表该信号是否被阻塞。而handle是一个函数指针数组,他的每个位置都对应信号的处理方法,不修改则为默认,可以通过系统调用进行自定义。

当信号到来时,OS就会遍历pending位图,为0则查看下一个比特位,为1则查看block位图的对应位置,此时block的该比特位为1则不做处理(被阻塞),为0则将对应位置pending置0再执行对应位置的handle操作。

信号的捕捉

信号的捕捉流程

 内核态对比用户态最明显的区别的内核态拥有更大的权力。所以进行自定义的信号处理时,要从内核态回到用户态,这是对操作系统的保护,防止用户定义的函数在内核态进行非法操作。

signal函数 

作用:捕捉一个指定信号,设定该信号的操作方法。

#include <iostream>
#include <unistd.h>
#include <signal.h>

void sigcb(int sig)
{
    std::cout << "get a sig : " << sig << std::endl;
}

int main()
{
    signal(2, sigcb);
    while (true)
    {
        std::cout << "process is running , pid : " << getpid() << std::endl;
        sleep(1);
    }
    return 0;
}

向进程3348发送2号信号,进程收到信号后执行了sigcb函数。 

 sigaction函数

作用:捕捉一个指定信号,设定该信号的操作方法。

#include <iostream>
#include <unistd.h>
#include <signal.h>

void sigcb(int sig)
{
    std::cout << "get a sig : " << sig << std::endl;
}

/*struct sigaction {
    void (*sa_handler)(int);
    void (*sa_sigaction)(int, siginfo_t *, void *);
    sigset_t sa_mask;
    int sa_flags;
    void (*sa_restorer)(void);
}
*/

int main()
{
    struct sigaction act;
    act.sa_handler = sigcb;
    sigaction(2, &act, nullptr);
    while (true)
    {
        std::cout << "process is running , pid : " << getpid() << std::endl;
        sleep(1);
    }
    return 0;
}

sigprocmask函数 

作用: sigprocmask函数用于检查或修改当前进程的信号屏蔽字(signal mask)

#include <iostream>
#include <unistd.h>
#include <signal.h>

void PrintfPending(sigset_t &pending)
{
    std::cout << "cur process pid : " << getpid() << "\n";
    std::cout << "pending signo :";
    for (int signo = 31; signo >= 1; signo--)
    {
        if (sigismember(&pending, signo))
        {
            std::cout << 1;
        }
        else
        {
            std::cout << 0;
        }
    }
    std::cout << "\n";
}

int main()
{
    signal(2, handler);

    sigset_t block_set, old_set;
    sigemptyset(&block_set);
    sigemptyset(&old_set);
    sigaddset(&block_set, 2);

    sigprocmask(SIG_BLOCK, &block_set, &old_set);

    while (true)
    {
        sigset_t pending;
        sigpending(&pending);

        PrintfPending(pending);
        sleep(2);
    }
    return 0;
}
举报

相关推荐

0 条评论