返回顶部
首页 > 资讯 > 操作系统 >【Linux从入门到精通】信号(信号保存 & 信号的处理)
  • 551
分享到

【Linux从入门到精通】信号(信号保存 & 信号的处理)

运维linux信号处理 2023-09-29 18:09:42 551人浏览 泡泡鱼
摘要

  本篇文章接着信号(初识信号 & 信号的产生)进行讲解。学完信号的产生后,我们也了解了信号的一些结论。同时还留下了很多疑问: 上篇文章所说的所有信号产生,最终都要有OS来进行执行,为什么呢?OS是进程的管理者。信号的处理是否是立即

  本篇文章接着信号(初识信号 & 信号的产生)进行讲解。学完信号的产生后,我们也了解了信号的一些结论。同时还留下了很多疑问:

  1. 上篇文章所说的所有信号产生,最终都要有OS来进行执行,为什么呢?OS是进程的管理者
  2. 信号的处理是否是立即处理的?在合适的时候。具体是指什么时候呢?
  3. 信号如果不是被立即处理,那么信号是否需要暂时被进程记录下来?会的。记录在哪里最合适呢?
  4. 一个进程在没有收到信号的时候,能否能知道,自己应该对合法信号作何处理呢?知道。程序员已经在操作系统內部提供了对信号的处理机制
  5. 如何理解OS向进程发送信号?能否描述一下完整的发送处理过程呢?

  接下来带着上述的疑问,本篇文章都会进行详细解释。

文章目录

目录

一、阻塞信号

1、1 信号的相关概念

1、2 阻塞信号的引入

1、3 sigset_t 及其相关操作

1、3、1 sigset_t 介绍

1、3、2 sigprocmask函数详解

1、3、3 阻塞信号演示

二、9号信号 SIGKILL 与 19号信号 SIGSTOP

2、1 自定义捕捉所有信号(No)

2、2 阻塞所有信号(No)

三、信号处理

3、1 什么时候处理信号合适呢?

3、2 信号处理的过程

3、3 sigaction()函数

四、为什么要引入信号


🙋‍♂️ 作者:@Ggggggtm 🙋‍♂️

👀 专栏:Linux从入门到精通  👀

💥 标题:信号保存和处理💥

 ❣️ 寄语:与其忙着诉苦,不如低头赶路,奋路前行,终将遇到一番好风景 ❣️  

一、阻塞信号

1、1 信号的相关概念

  我们之前学了信号的一些概念。接下来在学习一下信号的常用专业概念:

  • 实际执行信号的处理动作称为信号递达(Delivery)。

  • 信号从产生到递达之间的状态,称为信号未决(Pending)
  • 进程可以选择阻塞 (Block )某个信号。
  • 被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。
  • 注意:阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。

  只有概念是不行的,我们不妨来看一下在内核中是怎么进行表示这新概念的。

1、2 阻塞信号的引入

  之前我们说到,信号是存储在进程控制块内部的一个位图中。那么我们来看一下在内核中到底是怎么进行表示的。具体如下图:

  block 位图的结构与 pending 位图的结构一摸一样,都是用位图来表示的。pending 位图表示的该信号发送了但是还没有被处理(也就是暂时保存了起来)。block 位图表示的是信号被阻塞了(不能够直接处理该信号,除非清除该信号所对应block位图的标记)handler 所对应的就是就是一个函数指针数组。里面包括了 SIG_IGN 、SIG_DFL 和我们自己定义的捕捉信号的方法。

  SIG_DFL、SIG_IGN 分别对应的是0和1。只不过是进行了强制类型转换,转换成了函数指针类型。我们也不难理解,函数指针数组的下标就是信号的编号,函数指针数组所指向的内容就是信号标号的处理方法

  为了更好的理解阻塞信号,我们在对上图进行详细解释:

  • 每个信号都有两个标志位分别表示阻塞(block)和未决(pending),还有一个函数指针表示处理动作。信号产生时,内核在进程控制块中设置该信号的未决标志,直到信号递达才清除该标志。在上图的例子中,SIGHUP信号未阻塞也未产生过,当它递达时执行默认处理动作。
  • SIGINT信号产生过,但正在被阻塞,所以暂时不能递达。虽然它的处理动作是忽略,但在没有解除阻塞之前不能忽略这个信号,因为进程仍有机会改变处理动作之后再解除阻塞。
  • SIGQUIT信号未产生过,一旦产生SIGQUIT信号将被阻塞,它的处理动作是用户自定义函数sighandler。如果在进程解除对某信号的阻塞之前这种信号产生过多次,将如何处理?下文也会举例解释。

  下面我们来看一个实际的例子,来理解阻塞信号。

1、3 sigset_t 及其相关操作

1、3、1 sigset_t 介绍

  我们知道:在语言层面,语言会给我们提供 .h/.hpp 头文件。并且语言有属于自己的自定义类型。那么操作系统也会给我们提供 .h 和 OS自定义的类型。sigset_t 就是OS的自定义类型。

  sigset_t是一个数据类型,用于在C/C++语言中表示信号集。通过使用信号集,可以管理给定进程或线程中的各种信号。通俗理解,sigset_t 底层就是位图未决和阻塞标志可以用相同的数据类型sigset_t来存储,这个类型可以表示每个信号的“有效”或“无效”状态,在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞,而在未决信号集中“有效”和“无效”的含义是该信号是否处于未决状态。

  sigset_t 类型对象不允许用户自己直接进行位操作,可以使用一些函数来对sigset_t进行操作,包括添加、删除、检查、清空信号。下面是一些与sigset_t相关的常用函数:

  1. sigemptyset(sigset_t *set):将信号集set清空,表示不包含任何信号。

  2. sigfillset(sigset_t *set):将信号集set设置为包含所有信号。

  3. sigaddset(sigset_t *set, int signum):将指定信号signum添加到信号集set中。

  4. sigdelset(sigset_t *set, int signum):将指定信号signum从信号集set中删除。

  5. sigismember(const sigset_t *set, int signum):检查指定信号signum是否在信号集set中存在。

  6. sigprocmask(int how, const sigset_t *set, sigset_t *oldset):用于修改进程的信号屏蔽字(signal mask)。how参数指定了如何修改信号屏蔽字,可以是SIG_BLOCK、SIG_UNBLOCK或SIG_SETMASK。set参数是一个要更新的新信号屏蔽字,而oldset参数则是保存之前的信号屏蔽字。

  7. sigpending(sigset_t *set):获取进程中当前未决(pending)的信号集合。未决信号是已经产生但还没有被处理的信号。

1、3、2 sigprocmask函数详解

  sigprocmask函数是一个操作信号屏蔽字的系统调用函数,用于设置当前进程的信号屏蔽字(signal mask),从而控制信号的阻塞和解除阻塞。函数原型:

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

参数解释:

  • how:表示信号屏蔽字的操作方式,可以使用下面的常量:
    • SIG_BLOCK:将set中的信号集合添加到当前的信号屏蔽字中。
    • SIG_UNBLOCK:将set中的信号集合从当前的信号屏蔽字中移除。
    • SIG_SETMASK:将set中的信号集合替换为当前的信号屏蔽字。
  • set:指向要设置的信号集合的指针。
  • oldset:用于保存之前的信号屏蔽字的指针。

函数返回值:

  • 成功执行时,返回0。
  • 出现错误时,返回-1,并设置errno来指示错误类型。

函数功能:

  • 通过调用sigprocmask函数,可以在进程运行过程中更改信号屏蔽字,从而控制哪些信号被阻塞,哪些信号被接收。
  • 当我们设置一个信号屏蔽字时,相关信号将被阻塞,无法触发信号处理函数。
  • 通过修改信号屏蔽字,可以在需要的时候阻塞指定信号,也可以在不需要阻塞时解除信号屏蔽。

使用示例:

#include int main() {    sigset_t mask;    sigemptyset(&mask);   // 清空信号集合    sigaddset(&mask, SIGINT);   // 添加SIGINT信号到信号集合        // 将SIGINT信号添加到当前进程的信号屏蔽字中    if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {        perror("sigprocmask");        return 1;    }    // 执行其他操作    // 解除阻塞SIGINT信号    if(sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1){        perror("sigprocmask");        return 1;    }     return 0;}

  上述示例中,首先创建一个空的信号集合mask,并将SIGINT信号添加到该集合中。然后调用sigprocmask函数将SIGINT信号添加到当前进程的信号屏蔽字中,从而阻塞该信号的触发。在某些需要保证信号不被处理的临界区代码中,可以使用这种方式阻塞信号。接下来的操作可以在无需考虑SIGINT信号的影响下进行。最后,通过调用sigprocmask函数并传递SIG_UNBLOCK参数,可以解除对SIGINT信号的阻塞。

1、3、3 阻塞信号演示

  通过我们上述了解到的sigset_t 和其相关操作函数,那么接下来我们就写一段代码来演示一下阻塞的信号。

  我们的主要思路是:先阻塞(屏蔽)的信号2(SIGINT)。代码通过循环不断地打印pending信号位图,在发送信号2之前,信号2的pending状态一直为0。当我们发送信号2后,由于信号2被阻塞,所以并不能立刻处理信号2。此时信号2的pending状态就会变为1。在信号被解除屏蔽之前,信号2的pending状态一直为1,表示有一个信号2没有被递达。而在解除屏蔽后,如果在运行过程中产生了信号2,就会立即处理该信号,pending位图中的位置将显示为0,表示所有的信号都已经被递送处理

// 打印 pending 位图void showPending(sigset_t &pending){    for (int sig = 1; sig <= 31; sig++)    {        // 检查是否在信号集pending中,并打印        if (siGISmember(&pending, sig))            std::cout << "1";        else            std::cout << "0";    }    std::cout << std::endl;}int main(){    // 1. 定义信号集对象    sigset_t bset, obset;    sigset_t pending;    // 2. 初始化    sigemptyset(&bset);    sigemptyset(&obset);    sigemptyset(&pending);    // 3. 添加要进行屏蔽的信号    sigaddset(&bset, 2 );    // 4. 设置set到内核中对应的进程内部[默认情况进程不会对任何信号进行block]    int n = sigprocmask(SIG_BLOCK, &bset, &obset);    assert(n == 0);    (void)n;    std::cout << "block 2 号信号成功...., pid: " << getpid() << std::endl;    // 5. 重复打印当前进程的pending信号集    int count = 0;    while (true)    {        // 5.1 获取当前进程的pending信号集        sigpending(&pending);        // 5.2 显示pending信号集中的没有被递达的信号        showPending(pending);        sleep(1);        count++;        if (count == 20)        {            std::cout << "解除对于2号信号的block" << std::endl;            int n = sigprocmask(SIG_SETMASK, &obset, nullptr);            assert(n == 0);            (void)n;        }    }    return 0;}

  那我们接下来看看是否与我们所预期的结果相同。具体如下:

  结果与我们所预料的基本上相同。只不过是看不到解除2号信号后的 pending 位图。因为一旦解除,就会执行该信号进程就会退出。当然,我们可以进行自定义捕捉,然后再打印。

二、9号信号 SIGKILL 与 19号信号 SIGSTOP

  学完信号阻塞后,如果我们对所有的信号都进行设置block阻塞,我们是不是就写了一个不会被异常或者用户杀掉的进程? 

  同时,如果我们对所有的信号都进行了自定义捕捉,那我们是不是也就写了一个不会被异常或者用户杀掉的进程?

  我们不妨来自己验证一下,看看到底是否能像完成我们所想的那样。

2、1 自定义捕捉所有信号(No)

  代码很简单,我们不再作过多解释:

void catchSig(int signum){    std::cout << "获取一个信号: " << signum << std::endl;}int main(){    for(int sig = 1; sig <= 31; sig++) signal(sig, catchSig);    while(true) sleep(1);    return 0;}

  那我们来看看运行结果:

  其实并不是能够将所有信号进行自定义捕捉。通过上述测试,我们发现9号信号不可被自定义捕捉。实际上,19号信号SIGSTOP和9号信号SIGKILL是两个信号,不可被应用程序进行自定义捕获的

2、2 阻塞所有信号(No)

  我们直接看代码:

void blockSig(int sig){    sigset_t bset;    sigemptyset(&bset);    sigaddset(&bset, sig);    int n = sigprocmask(SIG_BLOCK, &bset, nullptr);    assert(n == 0);    (void)n;}void showPending(sigset_t &pending){    for (int sig = 1; sig <= 31; sig++)    {        if (sigismember(&pending, sig))            std::cout << "1";        else            std::cout << "0";    }    std::cout << std::endl;}int main(){    for(int sig = 1; sig <= 31; sig++)    {        blockSig(sig);    }    sigset_t pending;    while(true)    {        sigpending(&pending);        showPending(pending);        sleep(1);    }    return 0;}

  运行结果如下:

  实际上也不能阻塞所有信号。如上图情况。

  SIGSTOP和SIGKILL是两个特殊的信号,它们有一些不同于其他信号的特性。以下是它们不可被应用程序捕获、阻塞或忽略的原因:

  1. SIGSTOP:SIGSTOP是一个用于暂停进程执行的信号。当进程接收到SIGSTOP信号时,进程会立即停止执行并进入暂停状态。这个信号是由操作系统发出的,应用程序无法捕获、处理或阻塞该信号。这是为了保证系统能够强制终止进程的执行,以防止进程对系统造成不可预知的影响。

  2. SIGKILL:SIGKILL是一个用于强制终止进程的信号。当进程接收到SIGKILL信号时,进程会被立即终止,而且无法被阻塞或忽略。这个信号同样由操作系统发出,目的是确保应用程序无法继续执行。与SIGKILL不同的是,应用程序也不能捕获或处理SIGKILL信号。这是为了保证系统能够彻底终止某个进程,即使该进程可能不响应其他信号。

三、信号处理

3、1 什么时候处理信号合适呢?

  我们前面一直说会在合适的时候对信号进行处理。合适的时候具体的是什么呢?是从内核态切换到用户态的时候,会对信号进行检测和处理!

  内核态(Kernel Mode)和用户态(User Mode)是两个不同的执行环境,用于区分操作系统内核的特权级别和用户程序的特权级别。下面是对这两者的详细解释:

  1. 用户态(User Mode):

    • 用户态是指用户程序运行的环境,此时程序只能访问自身被授权的资源,如自身的内存空间、文件、设备等。
    • 在用户态下,应用程序不能直接访问和修改底层硬件资源,也无法执行特权指令和访问内核空间。
    • 用户态程序可以通过系统调用(System Call)向内核发起请求,以便获得更高级别的特权或访问系统资源。而系统调用会触发从用户态转换到内核态。
  2. 内核态(Kernel Mode):

    • 内核态是操作系统内核运行的环境,具有最高的特权级别。在这个特权级别下,操作系统具有完全掌控计算机硬件资源的权限。
    • 在内核态下,操作系统能够直接访问和操作所有的硬件资源,如处理器、内存、I/O设备等。它可以执行特权指令,控制内存分配和进程调度等底层操作。
    • 操作系统内核负责处理系统的底层任务,如中断处理、进程管理、内存管理、文件系统等。这些任务要求运行在内核态下才能完成。

  我们这里为什么会进入内核态呢?原因有很多,例如:系统调用、异常和中断处理、时间片等等原因。

3、2 信号处理的过程

  信号处理的整个过程如下:

  如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号。由于信号处理函数的代码是在用户空间的,处理过程比较复杂,举例如下: 用户程序注册了SIGQUIT信号的处理函数sighandler。 当前正在执行main函数,这时发生中断或异常切换到内核态。 在中断处理完毕后要返回用户态的main函数之前检查到有信号SIGQUIT递达。 内核决定返回用户态后不是恢复main函数的上下文继续执行,而是执行sighandler函数,sighandler和main函数使用不同的堆栈空间,它们之间不存在调用和被调用的关系,是 两个独立的控制流程。 sighandler函数返回后自动执行特殊的系统调用sigreturn再次进入内核态。 如果没有新的信号要递达,这次再返回用户态就是恢复main函数的上下文继续执行了。
  为什么在执行sighandler函数时,还需要返回用户态呢?只用在内核态的状态下执行不也可以吗?确实,内核能够且有权限执行sighandler函数,但是并不会去执行。为什么呢?因为操作系统是不信任我们任何人的!!!当我们处于内核态时,是操作系统内核运行的环境,具有最高的特权级别。万一用户自定义的sighandler函数有恶意程序呢?所以是要返回到用户态进行执行的。

3、3 sigaction()函数

  sigaction函数是一个用于设置信号处理函数的系统调用。它可以用于捕捉并处理各种类型的信号,如中断、故障、取消等。 函数原型如下:

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

  其中,signum表示要设置的信号编号,act是一个指向struct sigaction结构体的指针,用于设置该信号的处理方式,oldact是一个指向struct sigaction结构体的指针,用于保存原来的处理方式。struct sigaction结构体定义如下:

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

  sa_handler字段用于指定信号处理函数的地址。当信号到达时,系统会将控制权传递给该函数进行处理。sa_sigaction字段和sa_handler字段是互斥的,如果同时指定了这两个字段,以sa_sigaction字段为准

  sa_mask字段是一个信号屏蔽字,用于指定在信号处理函数执行期间需要被屏蔽的信号集合。也就是说,当信号处理函数执行时,除了属于sa_mask集合的信号外,其他信号都会被阻塞,直到该函数返回。

  sa_flags字段用于设置信号处理的一些标志。常用的标志包括:

  • SA_RESTART:设置系统调用被信号中断后自动重启;
  • SA_SIGINFO:指定信号处理函数有三个参数,可以额外获取信号的附加信息。

  sa_restorer字段是废弃字段,一般不使用。

  调用sigaction函数可以设置信号的处理方式。如果act为NULL,则表示忽略该信号;如果oldact不为NULL,则会将原来的处理方式保存到oldact中。

  成功调用sigaction函数时,返回0;失败时,返回-1,并设置errno以表明具体的错误原因。

  以下是一个使用sigaction函数的示例代码:

#include #include #include void sig_handler(int signum) {    printf("Received signal %d\n", signum);}int main() {    struct sigaction sa,osa;        sa.sa_handler = sig_handler; // 设置信号处理函数    sigemptyset(&sa.sa_mask); // 清空信号屏蔽字    sa.sa_flags = 0; // 标志位置0    if (sigaction(SIGINT, &sa, NULL) == -1) { // 设置SIGINT信号的处理方式        perror("sigaction error");        exit(EXIT_FAILURE);    }    printf("Waiting for signal...\n");        // 设置信号屏蔽字    sigaddset(&sa.sa_mask, 3);    sigaddset(&sa.sa_mask, 4);    sigaddset(&sa.sa_mask, 5);    sigaddset(&sa.sa_mask, 6);    sigaddset(&sa.sa_mask, 7);    // 设置进当前调用进程的pcb中    sigaction(2, &sa, &osa);        while(1) {        // 程序一直循环等待信号的到来    }    return 0;}

四、为什么要引入信号

  操作系统引入信号是为了实现进程间的通信和处理异步事件。信号是操作系统向进程发送的一种通知机制,用于向进程传递一些重要的事件或异常情况,比如用户键盘输入、硬件故障、进程终止等。

引入信号的目的有以下几点:

  1. 异步通知:信号机制允许操作系统在特定事件发生时异步地向进程发送信号,而不需要进程主动去轮询或等待这些事件。这样可以提高系统的响应速度和效率。

  2. 进程间通信:通过向进程发送信号,操作系统可以实现进程间的通信机制。其他进程可以发送信号给目标进程,从而进行协同工作、进行进程同步或传递重要的信息。

  3. 处理异常情况:信号可以用来处理进程运行过程中出现的异常情况,比如内存访问错误、除零错误等。当进程收到相应的信号后,可以采取相应的措施来处理异常,例如捕获信号并进行错误处理或进行进程终止等。

  操作系统引入信号的主要目的是为了实现进程间通信和处理异步事件。信号可以被看作是在特定情况下向进程发送的一种通知,用于通知进程发生了某个事件或条件。

信号可以用于以下几个方面:

  1. 处理中断:当操作系统接收到硬件发出的中断请求时,会发送相应的信号给进程,以便进程可以执行相应的中断处理程序。
  2. 进程间通信:通过发送信号,一个进程可以向另一个进程发送信号来传递信息。例如,父进程可以向子进程发送信号来通知其完成某个任务。
  3. 处理异常情况:当进程出现错误或异常时,操作系统可以向其发送一个相应的信号,进而及时处理该异常情况。
  4. 实现定时器和闹钟功能:操作系统可以通过发送信号来实现定时器和闹钟功能,以便在指定的时间触发某个操作。

  对于接收到的信号,进程可以选择忽略、捕捉、执行默认操作或者自定义操作。这样,操作系统可以更好地控制和管理进程的行为,提供更灵活和可靠的进程间通信和事件处理机制。

来源地址:https://blog.csdn.net/weixin_67596609/article/details/132831096

--结束END--

本文标题: 【Linux从入门到精通】信号(信号保存 & 信号的处理)

本文链接: https://lsjlt.com/news/421583.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 【Linux从入门到精通】信号(信号保存 & 信号的处理)
      本篇文章接着信号(初识信号 & 信号的产生)进行讲解。学完信号的产生后,我们也了解了信号的一些结论。同时还留下了很多疑问: 上篇文章所说的所有信号产生,最终都要有OS来进行执行,为什么呢?OS是进程的管理者。信号的处理是否是立即...
    99+
    2023-09-29
    运维 linux 信号处理
  • 【linux】进程信号——信号的保存和处理
    文章目录 一、阻塞信号1.1 信号的相关概念1.2 在内核中的构成 二、捕捉信号概念2.1 内核态和用户态2.2 信号捕捉流程图 三、信号操作3.1 sigset_t信号集3.2 信号集操作函数3.2.1 更改block表s...
    99+
    2023-08-20
    linux 运维 服务器
  • 【Linux从入门到精通】通信 | 共享内存(System V)
        本篇文章接着上篇文章通信 | 管道通信(匿名管道 & 命名管道)进行讲解。本篇文章的中点内容是共享内存。 文章目录  一、初识与创建共享内存 1、1 什么是共享内存 1、2 共享内存函数 1、2、1 创建共享内存 ...
    99+
    2023-10-01
    linux 运维 通信 共享内存
  • linux信号解释(3)--信号处理机制
        如果需要进程捕获某个信号,并作出相应的处理,就需要注册信号处理函数(其实就是内核里需要识别信号函数,类似C语言里的include某函数库)。    处理信号就类似软中断,内核为每个进程准备了一段信号向量表,记录信号的处理机制。当某个...
    99+
    2023-01-31
    信号处理 信号 机制
  • Ruby信号处理的方法
    这篇文章主要介绍“Ruby信号处理的方法”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Ruby信号处理的方法”文章能帮助大家解决问题。Ruby使用Process.kill发送信号Process.ki...
    99+
    2023-06-30
  • PHP入门指南:信号量和共享内存
    PHP作为一种脚本语言,在网络应用中有着广泛的应用。一般而言,PHP不是一个与系统底层操作相关的语言,但在一些特殊的场景下,如并发编程、多进程编程、进程间通信等,还是需要对系统底层有一定的了解。本文将介绍两个与进程间通信相关的底层知识:信号...
    99+
    2023-05-20
    PHP 信号量(Semaphore) 共享内存(Shared memory)
  • python 对信号 处理的 测试
     python 对信号 处理的测试 小结下: 每次信号 会将当前执行的函数挂起,进入 信号处理函数 如果信号处理函数还在处理,又来信号,当前函数仍然被挂起 执行完毕回到刚才挂起点继续执行 从下面输出 我们就可以看出来 ...
    99+
    2023-01-31
    信号 测试 python
  • Linux协程与信号处理的兼容性
    在Linux系统中,协程与信号处理有一定的兼容性问题。由于协程是一种用户态的轻量级线程,它们通常是由用户程序来实现,而信号处理是由操作系统来处理的。在使用协程时,需要注意以下几点与信号处理的兼容性问题: 阻塞信号:在协程中,如果需要阻塞...
    99+
    2024-08-06
    linux
  • 信号处理板卡学习资料:基于6UVPX C6678+XCVU9P的信号处理板卡440
    基于6UVPX C6678+XCVU9P的信号处理板卡...
    99+
    2023-06-05
  • 深入理解Django的信号机制
    目录Django的信号Django信号的使用自定义信号扩展:查看Django信号的接受者扩展:Django内置信号Django的信号 Django的信号机制不同于Linux的信号机制...
    99+
    2023-02-08
    Django 信号机制
  • python中对信号的处理详解
    目录什么是信号Python的信号处理Python对信号的处理信号枚举信号函数signal.alarm(time)signal.pause()signal.setitimer(whic...
    99+
    2024-04-02
  • Java接入微信支付超级详细教程——从入门到精通
    源码下载 源码获取:点击获取源码 本文介绍了“二维码付款”的代码。其他微信支付方式的代码都在源码中。 一、准备开发所需的账号以及配置信息 解释:想要接入微信支付我们需要两个玩意 ,一个是公众号/小程序/企业微信(开发用的),一个是微信支付商...
    99+
    2023-08-17
    微信 java 微信小程序
  • 阿里云服务器短信群发教程从入门到精通
    本文将详细介绍如何在阿里云服务器上进行短信群发。包括选择适合的短信服务、设置短信群发参数、编写短信发送代码等步骤。无论你是初学者还是有一定经验的开发者,都可以从本文中获得帮助。 阿里云服务器是阿里云推出的一种云服务器产品,它可以提供弹性的计...
    99+
    2023-12-16
    阿里 短信群发 入门
  • Linux下的Python自然语言处理:从入门到精通
    随着数据时代的到来,自然语言处理(NLP)越来越受到人们的关注。在NLP领域中,Python成为了最受欢迎的编程语言。Python有着简单易学、代码简洁、库丰富等优点,使得Python成为了NLP领域中的首选语言。本文将介绍Linux下的...
    99+
    2023-10-15
    linux 自然语言处理 linux
  • Python强大的信号库blinker入门详细教程
    目录1、信号2、blinker 使用2.1 命名信号2.2 匿名信号2.3 组播信号2.4 接收方订阅主题2.5 装饰器用法2.6 可订阅主题的装饰器2.7 检查信号是否有接收者2....
    99+
    2024-04-02
  • MYSQL中对信号的处理(SIGTERM,SIGQUIT,SIGHUP等)
    原创,因为LINUX系统编程水平有限某些用词不当请指出 一、信号处理以及多线程先信号处理基础知识 在LINUX中信号是一种由内核处理的一种软中断机制,他满足简单、不能携带大量信息、并且要满足一定条件才会发...
    99+
    2024-04-02
  • C++信号处理sigaction函数的测试分析
    本篇内容主要讲解“C++信号处理sigaction函数的测试分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C++信号处理sigaction函数的测试分析”吧!运行结果如图到此,相信大家对“C...
    99+
    2023-06-04
  • 如何分析Java开源工具在linux上的信号处理
    今天就跟大家聊聊有关如何分析Java开源工具在linux上的信号处理,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。当java虚拟机启动的时候,会启动很多内部的线程,这些线程主要在th...
    99+
    2023-06-17
  • Windows 上的 Go 文件处理教程:从入门到精通!
    Go 语言是一种现代化的编程语言,它在速度和可靠性方面都表现出色,因此越来越多的开发者开始选择使用它。Go 语言在处理文件方面也非常出色,它提供了一系列的标准库和功能,可以让你轻松地读取、写入、修改文件。在本文中,我们将深入探讨在 Win...
    99+
    2023-11-10
    windows 文件 教程
  • Python实现快速保存微信公众号文章中的图片
    目录一、实现效果(以槿泉壁纸为例)二、实现过程三、源码四、Python正则表达式匹配日期与时间一、实现效果(以槿泉壁纸为例) 二、实现过程 1.新建一个link文本,将需要下...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作