广告
返回顶部
首页 > 资讯 > 操作系统 >浅谈Linux信号机制
  • 942
分享到

浅谈Linux信号机制

Linux信号机制 2022-06-03 14:06:42 942人浏览 八月长安
摘要

目录一、信号列表1.1、实时信号非实时信号1.2、信号状态1.3、信号生命周期1.4、信号的执行和注销二、信号掩码和信号处理函数的继承2.1、信号处理函数的继承2.2、信号掩码的继承2.3、sigwait 与多线程2

目录
  • 一、信号列表
    • 1.1、实时信号非实时信号
    • 1.2、信号状态
    • 1.3、信号生命周期
    • 1.4、信号的执行和注销
  • 二、信号掩码和信号处理函数的继承
    • 2.1、信号处理函数的继承
    • 2.2、信号掩码的继承
    • 2.3、sigwait 与多线程
    • 2.4、多进程下的信号
  • 三、apis
    • 3.1、信号发生函数
    • 3.2、信号处理函数
    • 3.3、信号掩码函数
    • 3.4、信号集合变量
    • 3.5、信号屏蔽函数

一、信号列表

root@ubuntu:# kill -l

 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP

 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1

11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM

16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP

21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ

26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGio 30) SIGPWR

31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3

38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8

43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13

48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12

53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7

58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2

63) SIGRTMAX-1 64) SIGRTMAX

其中最常见的:

  • Ctrl + C 触发的是 SIGINT;
  • Ctrl + \ 触发的是SIGQUIT;
  • 但是特别说明下 Ctrl + D 并不是触发信号,而是产生一个 EOF,这也是为什么在 python 交互模式按下这个组合会退出 Python 的原因。

1.1、实时信号非实时信号

如上,kill列举出所有信号。实时信号与非实时信号又叫做可靠信号与不可靠信号。SIGRTMIN 及其以后的是实时信号,之前的是非实时信号。区别是实时信号支持重复排队,但是非实时信号不支持。非实时信号在排队时候会默认只出现一次,意思就是即使多次发送也终将只收到一个。在队列的取出顺序上也有区别,即最先取出的信号一定是实时信号。

PS:

  • kill、killall 默认发送SIGTERM 信号。
  • linux下 SIGKILL不能被阻塞、或忽略。
  • 默认情况下 SIGCHLD 不被忽略,编程时候需要注意这个(要么设置 SIG_IGN 或者主动 wait)。
  • 所有未定义处理函数的信号,默认退出进程。
  • 信号被设置block后仍存在于队列中只是不被处理,如果放开屏蔽将会被处理。
  • 信号可以中断sleep调用引起睡眠的进程。

1.2、信号状态

信号的”未决“是一种状态,指的是从信号的产生到信号被处理前的这一段时间;信号的”阻塞“是一个开关动作,指的是阻止信号被处理,但不是阻止信号产生。

例如在sleep前用 sigprocmask 阻塞了退出信号,然后sleep,然后在sleep的过程中产生一个退出信号,但是此时退出信号被阻塞过,(中文的”阻塞”在这里容易被误解为一种状态,实际上是一种类似于开关的动作,所以说“被阻塞过”,而不是“被阻塞”)所以处于“未决”状态,在 sleep后又用sigprocmask关掉退出信号的阻塞开关,因为之前产生的退出信号一直处于未决状态,当关上阻塞开关后,马上退出“未决”状态,得到处理,这一切发生在sigprocmask返回之前。

1.3、信号生命周期

对于一个完整的信号生命周期(从信号发送到相应的处理函数执行完毕)来说,可以分为三个重要的阶段,这三个阶段由四个重要事件来刻画:

1.信号诞生;

2. 信号在进程中注册完毕;

3.信号在进程中的注销完毕;

4.信号处理函数执行完毕。相邻两个事件的时间间隔构成信号生命周期的一个阶段。

下面阐述四个事件的实际意义:

  • 信号"诞生"。信号的诞生指的是触发信号的事件发生(如检测到硬件异常、定时器超时以及调用信号发送函数kill()或sigqueue()等)。
  • 信号在目标进程中"注册";进程的task_struct结构中有关于本进程中未决信号的数据成员:

struct sigpending pending;
struct sigpending
{
    struct sigqueue *head, **tail;
    sigset_t signal;
};

信号在进程中注册指的就是信号值加入到进程的未决信号集中(sigpending结构的第二个成员sigset_t signal),并且信号所携带的信息被保留到未决信号信息链的某个sigqueue结构中。只要信号在进程的未决信号集中,表明进程已经知道这些信号的存在,但还没来得及处理,或者该信号被进程阻塞。

1.信号在进程中的注销。在目标进程执行过程中,会检测是否有信号等待处理(每次从系统空间返回到用户空间时都做这样的检查)。如果存在未决信号等待处理且该信号没有被进程阻塞,则在运行相应的信号处理函数前,进程会把信号在未决信号链中占有的结构卸掉。是否将信号从进程未决信号集中删除对于实时与非实时信号是不同的。对于非实时信号来说,由于在未决信号信息链中最多只占用一个sigqueue结构,因此该结构被释放后,应该把信号在进程未决信号集中删除(信号注销完毕);而对于实时信号来说,可能在未决信号信息链中占用多个sigqueue结构,因此应该针对占用gqueue结构的数目区别对待:如果只占用一个sigqueue结构(进程只收到该信号一次),则应该把信号在进程的未决信号集中删除(信号注销完毕)。否则,不在进程的未决信号集中删除该信号(信号注销完毕)。进程在执行信号相应处理函数之前,首先要把信号在进程中注销。

2.信号生命终止。进程注销信号后,立即执行相应的信号处理函数,执行完毕后,信号的本次发送对进程的影响彻底结束。

1.4、信号的执行和注销

内核处理一个进程收到的软中断信号是在该进程的上下文中,因此,进程必须处于运行状态。当其由于被信号唤醒或者正常调度重新获得CPU时,在其从内核空间返回到用户空间时会检测是否有信号等待处理。如果存在未决信号等待处理且该信号没有被进程阻塞,则在运行相应的信号处理函数前,进程会把信号在未决信号链中占有的结构卸掉。当所有未被屏蔽的信号都处理完毕后,即可返回用户空间。对于被屏蔽的信号,当取消屏蔽后,在返回到用户空间时会再次执行上述检查处理的一套流程。

处理信号有三种类型:进程接收到信号后退出;进程忽略该信号;进程收到信号后执行用户设定用系统调用signal的函数。当进程接收到一个它忽略的信号时,进程丢弃该信号,就象没有收到该信号似的继续运行。如果进程收到一个要捕捉的信号,那么进程从内核态返回用户态时执行用户定义的函数。而且执行用户定义的函数的方法很巧妙,内核是在用户栈上创建一个新的层,该层中将返回地址的值设置成用户定义的处理函数的地址,这样进程从内核返回弹出栈顶时就返回到用户定义的函数处,从函数返回再弹出栈顶时,才返回原先进入内核的地方。这样做的原因是用户定义的处理函数不能且不允许在内核态下执行(如果用户定义的函数在内核态下运行的话,用户就可以获得任何权限)。

eg:


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

void myHandler(int num)
{
    int ret = 0;
    
    if (SIGUSR1 == num)
    {
        sigset_t set;
        ret = sigemptyset(&set);
        assert(!(-1 == ret));
        ret = sigaddset(&set, SIGINT);
        assert(!(-1 == ret));
        ret = sigaddset(&set, SIGRTMIN);
        assert(!(-1 == ret));
        ret = sigprocmask(SIG_UNBLOCK, &set, NULL);
        assert(!(-1 == ret));
        printf("解除阻塞 recv sig num: %d\n", num);
    }
    else if (num == SIGINT || num == SIGRTMIN)
    {
        printf("recv sig num: %d\n", num);
    }
    else
    {
        printf(" 其他信号recv sig num: %d\n", num);
    }
}

int main(void)
{
    pid_t pid;
    int ret = 0;
    // 设置回调函数
    struct sigaction act;
    act.sa_handler = myHandler;
    act.sa_flags = SA_SIGINFO;
    // 注册非实时信号的处理函数
    ret = sigaction(SIGINT, &act, NULL);
    assert(!(-1 == ret));
    // 注册实时信号的处理函数
    ret = sigaction(SIGRTMIN, &act, NULL);
    assert(!(-1 == ret));
    // 注册用户自定义信号
    ret = sigaction(SIGUSR1, &act, NULL);
    assert(!(-1 == ret));
    
    // 把 SIGINT  SIGRTMIN 军添加到阻塞状态字中
    sigset_t set;
    ret = sigemptyset(&set);
    assert(!(-1 == ret));
    ret = sigaddset(&set, SIGINT);
    assert(!(-1 == ret));
    ret = sigaddset(&set, SIGRTMIN);
    assert(!(-1 == ret));
    ret = sigprocmask(SIG_BLOCK, &set, NULL);
    assert(!(-1 == ret));
    
    pid = fork();
    assert(!(-1 == ret));
    if (0 == pid)
    {
        uNIOn sigval value;
        value.sival_int = 10;
        int i = 0;
        // 发三次不稳定信号
        for (i = 0; i < 3; i++)
        {
            ret = sigqueue(getppid(), SIGINT, value);
            assert(!(-1 == ret));
            printf("发送不可靠信号 ok\n");
        }
        
        // 发三次稳定信号
        value.sival_int = 20;
        for (i = 0; i < 3; i++)
        {
            ret = sigqueue(getppid(), SIGRTMIN, value);
            assert(!(-1 == ret));
            printf("发送可靠信号ok\n");
        }
        // 向父进程发送 SIGUSR1 解除阻塞
        ret = kill(getppid(), SIGUSR1);
        assert(!(-1 == ret));
    }
    while (1)
    {
        sleep(1);
    }
    return 0;
}

二、信号掩码和信号处理函数的继承

2.1、信号处理函数的继承

信号处理函数是进程属性,所以进程里的每个线程的信号处理函数是相同的。通过fork创建的子进程会继承父进程的信号处理函数。execve 后设置为处理的信号处理函数会被重置为默认函数,设置为忽略的信号保持不变。意思是如果父进程里信号设置处理为SIG_IGN,那么等到子进程被exec了,这个信号的处理还是被忽略,不会重置为默认函数。

eg:


// test.c --> test
#include <stdlib.h>
  
typedef void (*sighandler_t)(int);
static sighandler_t old_int_handler;
  
static sighandler_t old_handlers[SIGSYS + 1];
  
void sig_handler(int signo)
{
    printf("receive signo %d\n",signo);
    old_handlers[signo](signo);
}
  
int main(int argc, char **argv)
{
    old_handlers[SIGINT] = signal(SIGINT, SIG_IGN);
    old_handlers[SIGTERM] = signal(SIGTERM, sig_handler);
  
    int ret;
  
    ret = fork();
    if (ret == 0) {
        //child
        // 这里execlp将运行 test2 作为子进程。
        execlp("/tmp/test2", "/tmp/test2",(char*)NULL);
    }else if (ret > 0) {
        //parent
        while(1) {
            sleep(1);
        }
    }else{
        perror("");
        abort();
    }
  
}
  
================================================
test2.c --> test2
#include <stdio.h>
int main(int argc, char **argv)
{
    while(1) {
        sleep(1);
    }
    return 0;
}

结论:test换成test2后,SIGINT的处理方式还是忽略,SIGTERM被重置为默认的方式。

2.2、信号掩码的继承

信号掩码有以下规则:

1.每个线程可以有自己信号掩码。

2.fork出来的子进程会继承父进程的信号掩码,exec后信号掩码保持不变。如果父进程是多线程,那么子进程只继承主线程的掩码。

3.针对进程发送的信号,会被任意的没有屏蔽该信号的线程接收,注意只有一个线程会随机收到。linux下如果都可以所有线程都可以接收信号,那么信号将默认发送到主线程,posix系统是随机发送。

4.fork之后子进程里pending的信号集初始化为空,exec会保持pending信号集。


#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
  
typedef void (*sighandler_t)(int);
  
static void *thread1(void *arg)
{
    sigset_t set;
      
    printf("in thread1\n");
  
    sigemptyset(&set);
    sigaddset(&set, SIGTERM);
    pthread_sigmask(SIG_BLOCK, &set, NULL);

    while(1) {
        sleep(1);
    }
}
  
static void sigset_print(sigset_t *set)
{
    int i;
  
    for (i = 1; i <= SIGSYS; i++) {
        if (siGISmember(set, i)) {
            printf("signal %d is in set\n",i);
        }
    }
}
  
int main(int argc, char **argv)
{
    int ret;
    sigset_t set;
    pthread_t pid;
  
    pthread_create(&pid, NULL, thread1, NULL);
    sleep(1);
  
    sigemptyset(&set);
    sigaddset(&set, SIGINT);
    pthread_sigmask(SIG_BLOCK, &set, NULL);
  
    ret = fork();
    if (ret == 0) {
        //child
        pthread_sigmask(SIG_BLOCK, NULL, &set);
        sigset_print(&set);
  
        while(1) {
            sleep(1);
        }
    }else if (ret > 0) {
        //parent
        while(1) {
            sleep(1);
        }
    }else{
        perror("");
        abort();
    }
  
}

结论:只有在主线程里设置的掩码才被子进程继承了。这里面的原因在于linux里的fork只是复制了调用fork()的那个线程,因此在子进程里只有父进程的主线程被拷贝了,当然信号掩码就是父进程的主线程的信号掩码的复制了。再次验证证明,如果是在thread1里调用fork,那么子进程的信号掩码就会是thread1的拷贝了。

2.3、sigwait 与多线程

sigwait函数:sigwait等一个或者多个指定信号发生。

它所做的工作只有两个:

第一,监听被阻塞的信号;

第二,如果所监听的信号产生了,则将其从未决队列中移出来。sigwait并不改变信号掩码的阻塞与非阻塞状态。

在POSIX标准中,当进程收到信号时,如果是多线程的情况,我们是无法确定是哪一个线程处理这个信号。而sigwait是从进程中pending的信号中,取走指定的信号。这样的话,如果要确保sigwait这个线程收到该信号,那么所有线程含主线程以及这个sigwait线程则必须block住这个信号,因为如果自己不阻塞就没有未决状态(阻塞状态)信号,别的所有线程不阻塞就有可能当信号过来时,被其他的线程处理掉。

PS:

在多线程代码中,总是使用sigwait或者sigwaitinfo或者sigtimedwait等函数来处理信号。而不是signal或者sigaction等函数。因为在一个线程中调用signal或者sigaction等函数会改变所以线程中的信号处理函数,而不是仅仅改变调用signal/sigaction的那个线程的信号处理函数。

2.4、多进程下的信号

多进程下键盘触发的信号会同时发送到当前进程组的所有进程。如果一个程序在执行时 fork 了多个子进程,那么按键触发的信号将会被这个程序的所有进程收到。

但是与多线程不一样,多进程下的信号掩码和信号处理函数是独立的。每个进程都可以选择处理或者不处理,也可以设置自己的信号掩码。


#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>

int main(int argc, char **argv)
{
    pid_t pid = fork();

    signal(SIGCHLD, SIG_IGN);
    if (pid < 0)
        printf("error fork\n");
    else if (pid == 0)
    {
        signal(SIGINT, SIG_IGN); // 忽略 SIGINT,这样 ctrl+c 后子进程能活下来; 不设置的话,收到信号将退出
        printf("child gid = %ld\n", getpgid(getpid()));
        do
        {
            sleep(1);
        } while (1);
    }
    else
    {
        printf("parent gid = %ld\n", getpgid(getpid()));
        do
        {
            sleep(1);
        } while (1);
    }

    return 0;
}

如上图,可以看到,收到SIGINT 后父进程退出,子进程因为设置了忽略 SIGINT 所以子进程没有受到影响。

三、apis

3.1、信号发生函数

1.kill(pid_t pid, int signum);

2.int sigqueue(pid_t pid, int sig, const union sigval value);

3.pthread_kill(pthread_t tid, int signum);

4.raise(int signum);// 发送信号到自己

5.void alarm(void);

6.void abort(void);

7.int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);

PS:

sigqueue()比kill()传递了更多的附加信息,但sigqueue()只能向一个进程发送信号,而不能发送信号给一个进程组。如果signo=0,将会执行错误检查,但实际上不发送任何信号,0值信号可用于检查pid的有效性以及当前进程是否有权限向目标进程发送信号。

3.2、信号处理函数

1.signal(int signum, void (*handler)(int signum))

2.sigaction(int signum, struct sigaction* newact, sigaction* oldact)


sigaction act;
act.sa_handler = handler;
act.sa_flags = SA_SIGINFO;
// 注册信号的处理函数
sigaction(SIGINT, act, NULL);

3.3、信号掩码函数

1.sigprocmask(int how, struct sigaction* set,struct sigaction* oldset)

2.pthread_sigmask(int how, struct sigaction* set,struct sigaction* oldset)

sigprocmask用于设置进程的信号掩码,pthread_sigmask用于设置线程的信号掩码,二者参数相同。第一个参数有SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK

3.4、信号集合变量

sigset_t set

sigemptyset(&set) //清空阻塞信号集合变量

sigfillset(&set)  //添加所有的信号到阻塞集合变量里

sigaddset(&set,SIGINT) //添加单一信号到阻塞信号集合变量

sigdelset(&set,SIGINT) //从阻塞信号集合变量中删除单一信号

sigismember(&set,int signum) //测试信号signum是否包含在信号集合set中,如果包含返回1,不包含返回0,出错返回-1。错误代码也只有一个EINVAL,表示signum不是有效的信号代码。

3.5、信号屏蔽函数

1.int sigpending(sigset_t *set); // 返回阻塞的信号集

2.int sigsuspend(const sigset_t *mask);

sigsuspend表示临时将信号屏蔽字设为mask,并挂起进程直到有信号产生(非屏蔽信号才能唤醒或终止进程),如果信号处理函数返回,那么siguspend将恢复之前的信号屏蔽字(temporarily)

假设sisuspend阻塞进程时产生了信号A,且A不是mask内的屏蔽信号,那么A的信号处理函数有两种情形,

一:直接终止进程,此时进程都不存在了,那么sigsuspend当然无须返回了(不存在进程了sigsuspend也不存在了,函数栈嘛);

二:如果信号A的处理函数返回,那么信号屏蔽字恢复到sigsuspend之前的(sigsuspend调用时将信号屏蔽字设为mask,所以要恢复到sigsuspend调用之前的),然后sigsuspend返回-1并将error置为EINTR.

以上就是浅谈Linux信号机制的详细内容,更多关于Linux信号机制的资料请关注编程网其它相关文章!

--结束END--

本文标题: 浅谈Linux信号机制

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

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

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 浅谈Linux信号机制
    目录一、信号列表1.1、实时信号非实时信号1.2、信号状态1.3、信号生命周期1.4、信号的执行和注销二、信号掩码和信号处理函数的继承2.1、信号处理函数的继承2.2、信号掩码的继承2.3、sigwait 与多线程2...
    99+
    2022-06-03
    Linux 信号机制
  • 【Android】 浅谈Handler机制
    Handler机制产生的原因 在谈论一个机制之前,需要了解这个机制设计出来是为了解决什么问题。 Handler设计出来就是因为UI线程不能进行耗...
    99+
    2022-06-06
    handler机制 handler Android
  • 浅谈Java锁机制
    目录1、悲观锁和乐观锁2、悲观锁应用3、乐观锁应用4、CAS5、手写一个自旋锁1、悲观锁和乐观锁 我们可以将锁大体分为两类: 悲观锁 乐观锁 顾名思义,悲观锁总是...
    99+
    2022-11-12
  • 浅谈Python pygame绘制机制
    pygame绘制机制简介  屏幕控制 pygame.display • 用来控制Pygame游戏的屏幕 • Pygame有且只有一个屏幕 • 屏幕左上角坐标为(0,0) ...
    99+
    2022-06-02
    pygame绘制机制 python pygame
  • 浅谈Java内省机制
    目录概念JavaBean内省相关API代码案例:获取属性相关信息内省属性的注意事项完整代码概念 JavaBean 在实际编程中,我们常常需要一些用来包装值对象的类,例如Student...
    99+
    2022-11-13
    Java内省机制 Java内省
  • 浅谈Swift派发机制
    目录直接派发函数表派发消息机制派发具体派发直接派发 C++ 默认使用的是直接派发,加上 virtual 修饰符可以改成函数表派发。直接派发是最快的,原因是调用指令会少,还可以通过编译...
    99+
    2022-11-12
  • 浅谈Java 代理机制
    目录一、常规编码方式二、代理模式概述三、静态代理3.1、什么是静态代理3.2、代码示例四、Java 字节码生成框架五、什么是动态代理六、JDK 动态代理机制6.1、使用步骤6.2、代...
    99+
    2022-11-12
  • 浅谈AndroidDialog窗口机制
    目录问题引出Dialog源码分析构造方法show()方法问题引出 //创建dialog 方式一 AlertDialog.Builder builder=new AlertDialo...
    99+
    2022-11-13
  • 浅谈numpy广播机制
    目录Broadcast最简单的广播机制稍微复杂的广播机制广播机制到底做了什么一个正确的经典示例一种更便捷的计算方式Broadcast 广播是numpy对不同形状(shape)的数组进...
    99+
    2023-02-15
    numpy 广播机制
  • 浅谈Redis缓冲区机制
    目录Redis缓冲区机制客户端缓冲机制应对输入缓冲区溢出查看输入缓冲区信息如何解决输入缓冲区溢出应对输出缓冲区溢出Monitor命令的执行输出缓冲区设置不合理主从集群中的缓冲区复制缓...
    99+
    2022-11-13
  • 浅谈node的事件机制
    Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. 在nodejs的...
    99+
    2022-06-04
    浅谈 机制 事件
  • 浅谈Android Aidl 通讯机制
    服务端: 首先是编写一个aidl文件,注意AIDL只支持方法,不能定义静态成员,并且方法也不能有类似public等的修饰符;AIDL运行方法有任何类型的参数和返回值,在jav...
    99+
    2022-06-06
    aidl Android
  • 浅谈Redis的异步机制
    目录前言一、Redis 的阻塞点4 类交互对象和具体的操作之间的关系:切片集群实例交互时的阻塞点二、可以异步执行的阻塞点三、异步的子线程机制总结前言 命令操作、系统配置、关键机制、硬...
    99+
    2022-11-13
  • linux信号解释(3)--信号处理机制
        如果需要进程捕获某个信号,并作出相应的处理,就需要注册信号处理函数(其实就是内核里需要识别信号函数,类似C语言里的include某函数库)。    处理信号就类似软中断,内核为每个进程准备了一段信号向量表,记录信号的处理机制。当某个...
    99+
    2023-01-31
    信号处理 信号 机制
  • Linux信号机制是什么
    Linux信号机制是一种用于进程间通信的机制,用于在进程之间传递异步事件的通知。当某个进程接收到一个信号时,它可以选择忽略、捕获或默...
    99+
    2023-08-12
    Linux
  • 浅谈Servlet的Cookie和Session机制
    目录一、Servlet Cookies1.1 Cookies构成1.2 Servlet操作Cookie方法1.3 代码示例:1.4 验证结果二、Servlet Session2.1 ...
    99+
    2022-11-12
  • 浅谈Java垃圾回收机制
    目录一.什么是垃圾二.怎么回收垃圾2.1 静态对象什么时候变成垃圾被回收2.2 新生代和年老代三、垃圾回收算法3.1 标记清除算法3.2 复制清除算法(专门用于处理年轻代垃圾的)3....
    99+
    2022-11-12
  • 怎样浅谈Java访问控制机制
    怎样浅谈Java访问控制机制,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Java 访问控制机制的原理是:在某些策略配置文件中预定义好某些代码对某些资源具有某些操作权限,当...
    99+
    2023-06-17
  • 浅谈Android IPC机制之Binder的工作机制
    目录进程和线程的关系跨进程的种类Serializable,Parcelable接口Binder进程和线程的关系 按照操作系统中的描述,线程是CPU调度的最小单位,同时线程也是一种有限...
    99+
    2022-11-12
  • 浅谈Node异步编程的机制
    本文介绍了Node异步编程,分享给大家,具体如下: 目前的异步编程主要解决方案有: 事件发布/订阅模式 Promise/Deferred模式 流程控制库 事件发布/订阅模式 Node自身提供...
    99+
    2022-06-04
    浅谈 机制 Node
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作