信号signal编程测试

news2024/12/23 9:26:33

信号会打断系统调用,慎用,就是用的时候测一测。

下面是信号的基础测试

信号

信号(signal)机制是UNIX系统中最为古老的进程之间的通信机制。它用于在一个或多个进程之间传递异步信号。信号可以由各种异步事件产生,例如键盘中断等。Shell也可以使用信号将作业控制命令传递给它的子进程。
Linux系统中定义了一系列的信号,这些信号可以由内核产生,也可以由系统中的其他进程产生,只要这些进程有足够的权限。可以使用kill命令(kill -l)在机器上列出所有的信号,如下所示:

lkmao@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
lkmao@ubuntu:~$

进程可以屏蔽掉大多数的信号,除了SIGSTOP和SIGKILL。SIGSTOP信号使一个正在运行的进程暂停,而信号SIGKILL则使正在运行的进程退出。进程可以选择系统的默认方式处理信号,也可以选择自己的方式处理产生的信号。信号之间不存在相对的优先权,系统也无法处理同时产生的多个同种的信号,也就是说,进程不能分辨它收到的是1个或者是42个SIGCONT信号。

SIGCONT:此作业控制信号送给需要继续运行的处于停止状态的进程。如果接收到此信号的进程处于停止状态,则操作系统的默认动作是使该停止的进程继续运行,否则默认动作是忽略此信号。

SIGEMT:指示一个实现定义的硬件故障。

SIGFPE:此信号表示一个算术运算异常,例如除以0,浮点溢出等。

SIGHUP:如果终端界面检测到一个连接断开,则将此信号送给与该终端相关的进程。 SIGILL:此信号指示进程已执行一条非法硬件指令。

SIGINT:当用户按中断键(一般采用Delete或Ctrl+C)时,终端驱动程序产生这个信号并将信号送给前台进程组中的每一个进程。当一个进程在运行时失控,特别是它正在屏幕上产生大量不需要的输出时,常用此信号终止它。

SIGIO:此信号指示一个异步IO事件。

SIGIOT:这指示一个实现定义的硬件故障。

SIGPIPE:如果在读进程时已终止写管道,则产生此信号。

SIGQUIT:当用户在终端上按退出键(一般采用Ctrl+C)时,产生此信号,并送至前台进程组中的所有进程。

SIGSEGV:指示进程进行了一次无效的存储访问。

SIGSTOP:这是一个作业控制信号,它停止一个进程。

SIGSYS:指示一个无效的系统调用。由于某种未知原因,某个进程执行了一条系统调用命令,但是调用命令所用的参数无效。

SIGTERM:这是由kill命令发送的系统默认终止信号。

SIGTRAP:指示一个实现定义的硬件故障。

SIGTSTP:交互停止信号,当用户在终端上按挂起键(一般采用Ctrl+Z)时,终端驱动程序产生此信号。

SIGTTIN:当一个后台进程组进程试图读其控制终端时,终端驱动程序产生此信号。 SIGTTOU:当一个后台进程组进程试图写其控制终端时产生此信号。

SIGURG:此信号通知进程已经发生一个紧急情况。在网络连接上,接到非规定波特率的数据时,此信号可选择地产生。

SIGUSR1:这是一个用户定义的信号,可用于应用程序。

SIGUSR2:这是一个用户定义的信号,可用于应用程序。

 信号截取函数signal()

signal()函数用于截取系统的信号,对此信号挂接用户自己的处理函数。其原型如下:

NAME
       signal - ANSI C signal handling

SYNOPSIS
       #include <signal.h>

       typedef void (*sighandler_t)(int);

       sighandler_t signal(int signum, sighandler_t handler);

signal()函数的原型说明此函数要求两个参数,返回一个函数指针,而该指针所指向的函数无返回值(void)。第1个参数signo是一个整型数,第2个参数是函数指针,它所指向的函数需要一个整型参数,无返回值。用一般语言来描述就是要向信号处理程序传送一个整型参数,而它却无返回值。当调用signal设置信号处理程序时,第2个参数是指向该函数(也就是信号处理程序)的指针。signal的返回值指向以前信号处理程序的指针。
如下代码截取了系统的信号SIGSTOP和SIGKILL,用命令kill杀死其是不可能的。

测试一:尝试截获信号SIGSTOP和SIGKILL

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>

#define DEBUG_INFO(format, ...) printf("%s:%d -- " format "\n", __func__, __LINE__,##__VA_ARGS__)

typedef void (*sighandler)(int signo);

static void sig_kill(int signo){
    DEBUG_INFO("signo = %d\n", signo);
}

static void sig_stop(int signo){
    DEBUG_INFO("signo = %d\n", signo);
}

int main(int argc, char **argv){
    sighandler ret;
    ret = signal(SIGKILL, sig_kill);
    if(ret == SIG_ERR){
        perror("signal sig_kill");
        DEBUG_INFO("signal SIGKILL error");
        //exit(-1);
    }
    ret = signal(SIGSTOP, sig_stop);
    if(ret == SIG_ERR){
        perror("signal sig_stop");
        //exit(-1);
        DEBUG_INFO("signal SIGSTOP error");
    }
    for(;;){
        sleep(1);
    }
    return 0;
}

执行结果:

signal sig_kill: Invalid argument
main:28 -- signal SIGKILL error
signal sig_stop: Invalid argument
main:35 -- signal SIGSTOP error

结论:这根本截获不了啊。

测试二:捕获SIGINT,捕获成功以后,将SIGINT信号设置为默认处理方式

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>

#define DEBUG_INFO(format, ...) printf("%s:%d -- " format "\n", __func__, __LINE__,##__VA_ARGS__)

typedef void (*sighandler)(int signo);

static void sig_func(int signo){
    DEBUG_INFO("signo = %d\n", signo);
    switch(signo) {
        case SIGKILL:
        DEBUG_INFO("SIGKILL");
        break;
        case SIGSTOP:
        DEBUG_INFO("SIGSTOP");
        break;
        case SIGINT:
        DEBUG_INFO("SIGINT");
        signal(SIGINT, SIG_DFL);
        default:

        break;
    }
}
int main(int argc, char **argv){
    sighandler ret;
    ret = signal(SIGKILL, sig_func);
    if(ret == SIG_ERR){
        perror("signal sig_kill");
        DEBUG_INFO("signal SIGKILL error");
        //exit(-1);
    }
    ret = signal(SIGSTOP, sig_func);
    if(ret == SIG_ERR){
        perror("signal sig_stop");
        //exit(-1);
        DEBUG_INFO("signal SIGSTOP error");
    }
    ret = signal(SIGINT, sig_func);
    if(ret == SIG_ERR){
        perror("signal sig_stop");
        //exit(-1);
        DEBUG_INFO("signal SIGSTOP error");
    }
    for(;;){
        sleep(1);
    }
    return 0;
}

测试结果:按两次CTRL+C,第一次进入sig_func函数,第二次退出程序。

signal sig_kill: Invalid argument
main:37 -- signal SIGKILL error
signal sig_stop: Invalid argument
main:44 -- signal SIGSTOP error
^Csig_func:16 -- signo = 2

sig_func:25 -- SIGINT

kill函数和raise函数

NAME
       kill - send signal to a process

SYNOPSIS
       #include <sys/types.h>
       #include <signal.h>

       int kill(pid_t pid, int sig);
NAME
       raise - send a signal to the caller

SYNOPSIS
       #include <signal.h>

       int raise(int sig);

测试三:kill函数和raise函数发送信号

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>

#define DEBUG_INFO(format, ...) printf("%s:%d -- " format "\n", __func__, __LINE__,##__VA_ARGS__)

typedef void (*sighandler)(int signo);

static void sig_func(int signo){
    static int count = 0;
    DEBUG_INFO("signo = %d\n", signo);
    switch(signo) {
        case SIGKILL:
        DEBUG_INFO("SIGKILL");
        break;
        case SIGSTOP:
        DEBUG_INFO("SIGSTOP");
        break;
        case SIGINT:
        count++;
        DEBUG_INFO("SIGINT count = %d",count);
        if(count == 2){
            signal(SIGINT, SIG_DFL);
        }
        
        
        default:

        break;
    }
}
int main(int argc, char **argv){
    sighandler ret;
    ret = signal(SIGKILL, sig_func);
    if(ret == SIG_ERR){
        perror("signal sig_kill");
        DEBUG_INFO("signal SIGKILL error");
        //exit(-1);
    }
    ret = signal(SIGSTOP, sig_func);
    if(ret == SIG_ERR){
        perror("signal sig_stop");
        //exit(-1);
        DEBUG_INFO("signal SIGSTOP error");
    }
    ret = signal(SIGINT, sig_func);
    if(ret == SIG_ERR){
        perror("signal sig_stop");
        //exit(-1);
        DEBUG_INFO("signal SIGSTOP error");
    }
    raise(SIGINT);
    kill(getpid(),SIGINT);
    for(;;){
        sleep(1);
    }
    return 0;
}

测试结果:raise产生一次SIGINT信号,kill产生一次SIGINT信号,此时计数值count变成2,信号处理函数恢复默认值,最后CTRL+C退出进程。

signal sig_kill: Invalid argument
main:43 -- signal SIGKILL error
signal sig_stop: Invalid argument
main:50 -- signal SIGSTOP error
sig_func:17 -- signo = 2

sig_func:27 -- SIGINT count = 1
sig_func:17 -- signo = 2

sig_func:27 -- SIGINT count = 2
^C

SIGCHLD信号

测试程序:子进程退出时,会自动向父进程发送信号

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>

#define DEBUG_INFO(format, ...) printf("%s:%d -- " format "\n", __func__, __LINE__,##__VA_ARGS__)

typedef void (*sighandler)(int signo);

static void sig_func(int signo){
    static int count = 0;
    //DEBUG_INFO("signo = %d\n", signo);
    switch(signo) {
        case SIGKILL:
            DEBUG_INFO("SIGKILL");
            break;

        case SIGSTOP:
            DEBUG_INFO("SIGSTOP");
            break;

        case SIGINT:
            count++;
            DEBUG_INFO("SIGINT count = %d",count);
            if(count == 2){
                signal(SIGINT, SIG_DFL);
            }
            break;

        case SIGCHLD:
            DEBUG_INFO("%u get a SIGCHLD signal",getppid());
            break;       
        
        default:
            DEBUG_INFO("unknow signo = %d",signo);
            break;
    }
}
int main(int argc, char **argv){
    sighandler ret;
    ret = signal(SIGCHLD, sig_func);
    if(ret == SIG_ERR){
        perror("signal sig_kill");
        DEBUG_INFO("signal SIGKILL error");
        //exit(-1);
    }
    pid_t pid = fork();
    if(pid == 0){
        DEBUG_INFO("child running %u",getpid());
        DEBUG_INFO("send a SIGCHLD to %u",getppid());
        exit(0);
    }
    
    for(;;){
        sleep(1);
    }
    return 0;
}

执行结果:

main:54 -- child running 109007
main:55 -- send a SIGCHLD to 109006
sig_func:36 -- 

SIGABRT信号测试

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>

#define DEBUG_INFO(format, ...) printf("%s:%d -- " format "\n", __func__, __LINE__,##__VA_ARGS__)

typedef void (*sighandler)(int signo);

static void sig_func(int signo){
    static int count = 0;
    switch(signo) {
        case SIGABRT:
            break;
        case SIGKILL:
            DEBUG_INFO("SIGKILL");
            break;

        case SIGSTOP:
            DEBUG_INFO("SIGSTOP");
            break;

        case SIGINT:
            count++;
            DEBUG_INFO("SIGINT count = %d",count);
            if(count == 2){
                signal(SIGINT, SIG_DFL);
            }
            break;

        case SIGCHLD:
            DEBUG_INFO("%u get a SIGCHLD signal",getppid());
            break;       
        
        default:
            DEBUG_INFO("unknow signo = %d",signo);
            break;
    }
}
int main(int argc, char **argv){
    sighandler ret;
    ret = signal(SIGABRT, sig_func);
    if(ret == SIG_ERR){
        perror("signal");
        exit(-1);
    }
    DEBUG_INFO("send a SIGABRT signal by abort()");
    abort();
    sleep(1);
    return 0;
}

测试结果:

main:52 -- send a SIGABRT signal by abort()
./test.sh: 行 10: 111335 已放弃               (核心已转储) ./_build_test_cpp_test/signal

SIGCONT信号测试:实验中,父进程先睡眠,子进程向父进程发送SIGCONT信号,父进程退出睡眠,继续执行,然后退出程序。子进程变成孤儿进程,最后由进程1接管

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>

#define DEBUG_INFO(format, ...) printf("%s:%d -- " format "\n", __func__, __LINE__,##__VA_ARGS__)

typedef void (*sighandler)(int signo);

static void sig_func(int signo){
    static int count = 0;
    switch(signo) {
        case SIGABRT:
            break;
        case SIGKILL:
            DEBUG_INFO("SIGKILL");
            break;

        case SIGSTOP:
            DEBUG_INFO("SIGSTOP");
            break;

        case SIGINT:
            count++;
            DEBUG_INFO("SIGINT count = %d",count);
            if(count == 2){
                signal(SIGINT, SIG_DFL);
            }
            break;

        case SIGCHLD:
            DEBUG_INFO("%u get a SIGCHLD signal",getppid());
            break;       
        
        case SIGCONT:
            DEBUG_INFO("SIGCONT");
            break;

        default:
            DEBUG_INFO("unknow signo = %d",signo);
            break;
    }
}
int main(int argc, char **argv){
    sighandler ret;
    ret = signal(SIGCONT, sig_func);
    if(ret == SIG_ERR){
        perror("signal");
        exit(-1);
    }
    
    if(fork() == 0){
        DEBUG_INFO("%u send a SIGCONT signal",getppid());
        DEBUG_INFO("my parent is %u",getppid());
        kill(getppid(),SIGCONT);
        sleep(500);
        DEBUG_INFO("my parent is %u",getppid());
        DEBUG_INFO("bye bye");
        abort();
    }
    sleep(100);
    DEBUG_INFO("parent sleep is interrupt by signal SIGCONT");
    return 0;
}

执行结果:符合推到

main:58 -- 116350 send a SIGCONT signal
main:59 -- my parent is 116350
sig_func:41 -- SIGCONT
main:67 -- parent sleep is interrupt by signal SIGCONT
lkmao@ubuntu:/big/csi_driver/rty/01$ main:62 -- my parent is 1
main:63 -- bye bye

最后通过进程名字终止子进程的睡眠,它继续运行后,自行退出。 

killall -SIGCONT signal

SIGHUP信号

问:如何产生一个SIGHUP信号

可以通过以下几种方式产生SIGHUP信号:
1. 在终端中使用kill命令,指定进程ID和信号类型:

```
kill -SIGHUP <进程ID>
```

2. 在终端中使用kill命令,指定进程名称和信号类型:

```
killall -SIGHUP <进程名称>
```

3. 在程序中使用kill函数,指定进程ID和信号类型:

```c
kill(<进程ID>, SIGHUP);
```

4. 在程序中使用raise函数,产生当前进程的SIGHUP信号:

```c
raise(SIGHUP);
```

在什么情况下需要发送一个SIGHUP信号

SIGHUP信号通常用于重新加载配置文件或重新启动进程。以下是一些需要发送SIGHUP信号的情况:
1. 当进程的配置文件发生更改时,可以发送SIGHUP信号以重新加载配置文件。

2. 当进程需要重新启动时,可以发送SIGHUP信号以通知进程重新启动。

3. 当需要重新初始化进程时,可以发送SIGHUP信号以重新初始化进程。

4. 当需要重新读取进程的日志文件时,可以发送SIGHUP信号以重新打开日志文件。

5. 当需要重新加载进程的插件或模块时,可以发送SIGHUP信号以重新加载插件或模块。
 

测试代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>

#define DEBUG_INFO(format, ...) printf("%s:%d -- " format "\n", __func__, __LINE__,##__VA_ARGS__)

typedef void (*sighandler)(int signo);

static void sig_func(int signo){
    static int count = 0;
    switch(signo) {
        case SIGABRT:
            break;
        case SIGKILL:
            DEBUG_INFO("SIGKILL");
            break;

        case SIGSTOP:
            DEBUG_INFO("SIGSTOP");
            break;

        case SIGINT:
            count++;
            DEBUG_INFO("SIGINT count = %d",count);
            if(count == 2){
                signal(SIGINT, SIG_DFL);
            }
            break;

        case SIGCHLD:
            DEBUG_INFO("%u get a SIGCHLD signal",getppid());
            break;       
        
        case SIGCONT:
            DEBUG_INFO("SIGCONT %u",getppid());
            break;
        case SIGHUP:
            DEBUG_INFO("SIGHUP = %u",getpid());
            break;
        case SIGSYS:
            DEBUG_INFO("SIGSYS");
            break;
        case SIGTTOU:
            DEBUG_INFO("SIGTTOU");
            break;
        default:
            DEBUG_INFO("unknow signo = %d",signo);
            break;
    }
}
int main(int argc, char **argv){
    sighandler ret;
    ret = signal(SIGHUP,sig_func);
    if(ret == SIG_ERR){
        perror("signal");
        exit(-1);
    }
    DEBUG_INFO("pid = %u,ppid = %u",getpid(),getppid());
    if(fork() == 0){
        DEBUG_INFO("child %u",getpid());
        sleep(100);
        DEBUG_INFO("child %u",getpid());

    }
    
    sleep(100);
    DEBUG_INFO("parent sleep is interrupt by a signal");

    return 0;
}

 测试结果:结果证明

1 SIGHUP信号可以被捕获 

2 SIGHUP信号可以打断sleep睡眠。

3 父进程和子进程都收到了信号

 SIGUSR1和SIGUSR2

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>

#define DEBUG_INFO(format, ...) printf("%s:%d -- " format "\n", __func__, __LINE__,##__VA_ARGS__)

typedef void (*sighandler)(int signo);

static void sig_func(int signo){
    static int count = 0;
    switch(signo) {
        case SIGABRT:
            break;
        case SIGKILL:
            DEBUG_INFO("SIGKILL");
            break;

        case SIGSTOP:
            DEBUG_INFO("SIGSTOP");
            break;

        case SIGINT:
            count++;
            DEBUG_INFO("SIGINT count = %d",count);
            if(count == 2){
                signal(SIGINT, SIG_DFL);
            }
            break;

        case SIGCHLD:
            DEBUG_INFO("%u get a SIGCHLD signal",getppid());
            break;       
        
        case SIGCONT:
            DEBUG_INFO("SIGCONT %u",getppid());
            break;
        case SIGHUP:
            DEBUG_INFO("SIGHUP = %u",getpid());
            break;
        case SIGSYS:
            DEBUG_INFO("SIGSYS");
            break;
        case SIGTTOU:
            DEBUG_INFO("SIGTTOU");
            break;
        case SIGUSR1:
            DEBUG_INFO("SIGUSR1 = %u",getpid());
            break;
        case SIGUSR2:
            DEBUG_INFO("SIGUSR2 = %u",getpid());
            break;
        default:
            DEBUG_INFO("unknow signo = %d",signo);
            break;
    }
}
int main(int argc, char **argv){
    sighandler ret;
    ret = signal(SIGHUP,sig_func);
    if(ret == SIG_ERR){
        perror("signal");
        exit(-1);
    }
    ret = signal(SIGUSR1,sig_func);
    if(ret == SIG_ERR){
        perror("signal");
        exit(-1);
    }
    ret = signal(SIGUSR2,sig_func);
    if(ret == SIG_ERR){
        perror("signal");
        exit(-1);
    }
    DEBUG_INFO("pid = %u,ppid = %u",getpid(),getppid());
    if(fork() == 0){
        DEBUG_INFO("child %u",getpid());
        kill(getppid(), SIGUSR1);
        kill(getpid(), SIGUSR2);
        sleep(100);
        DEBUG_INFO("child %u",getpid());

    }
    
    for(int i = 0; i < 10;i++){
        sleep(100);
        DEBUG_INFO("parent sleep is interrupt by a signal");
    }
    

    return 0;
}

执行结果: 

main:80 -- pid = 126176,ppid = 126084
main:82 -- child 126177
sig_func:56 -- SIGUSR2 = 126177
sig_func:53 -- SIGUSR1 = 126176
main:92 -- parent sleep is interrupt by a signal

小结

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/504958.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构与算法1:引入概念

接下来系统的学一下数据结构与算法的知识&#xff0c;本章节是第一部分&#xff1a;数据结构与算法的进入与基本概述 第一章&#xff1a;引入概念 【铁打的算法demo】先来看到题&#xff1a; 如果 a b c 1000&#xff0c;且 a2 b2 c2&#xff08;a, b , c 为⾃然数&…

快进来,带你了解FPGA基础知识---lattice莱迪斯深力科MachXO2 FPGA系列简介

FPGA基础知识---lattice莱迪斯深力科MachXO2 LCMXO2-4000HC-4TG144I FPGA简介 FPGA基础知识&#xff1a;FPGA是英文Field&#xff0d;Programmable Gate Array的缩写&#xff0c;即现场可编程门阵列&#xff0c;它是在PAL、GAL、CPLD等可编程器件的基础上进一步发展的产物。它…

《程序员面试金典(第6版)》面试题 16.17. 连续数列(贪心算法思想,动态规划算法思想,C++)

题目描述 给定一个整数数组&#xff0c;找出总和最大的连续数列&#xff0c;并返回总和。 示例&#xff1a; 输入&#xff1a; [-2,1,-3,4,-1,2,1,-5,4] 输出&#xff1a; 6 解释&#xff1a; 连续子数组 [4,-1,2,1] 的和最大&#xff0c;为 6。进阶&#xff1a; 如果你已经实…

elementUI tabs切换 echarts宽度挤压到一起 由100%变成100px

被压缩的图表&#xff1a; 正常显示 <el-tabs v-model"activeName" type"card" tab-click"handleClick"><el-tab-pane name"first"></el-tab-pane><el-tab-pane name"second" label"未达成原因…

如何在Kali Linux中获得root权限?

根用户名或账户在Linux或任何其他类似Unix的操作系统中拥有所有可用命令和文件的默认权限。它也被称为超级用户、根账户和根用户。用户名&#xff1a;"kali "是登录新Kali系统的标准凭证。这建立了一个用户 "kali "的会话&#xff0c;你必须在 "Sudo …

Java—JDK8新特性—方法引用【内含思维导图】

目录 4.方法引用 思维导图 4.1 什么是方法引用 4.2 为什么要使用方法引用 4.3 方法引用语法 4.4 方法引用的5种情况使用示例 4.方法引用 思维导图 4.1 什么是方法引用 方法引用就是Lambda表达式&#xff0c;也就是函数式接口的一个实例&#xff0c;通过方法的名称来指向一…

Word怎么分页,提高效率就靠这3种方法!

案例&#xff1a;Word怎么分页 【文档要进行分页处理&#xff0c;但是我尝试了好多次还是不行&#xff01;大家知道Word怎么分页吗&#xff1f;】 在使用Microsoft Word处理文档时&#xff0c;我们常常需要进行分页操作。Word的分页功能可以将文档分成多个页面&#xff0c;以…

【Vue3 插件篇】GSAP 动画库与 图片预览插件

GSAP 动画库 GSAP&#xff08;GreenSock Animation Platform&#xff09;是一个专业的动画库&#xff0c;可以用它完成你想要的各种效果 官网地址&#xff1a;https://greensock.com/ 参考文章一&#xff1a;https://www.jianshu.com/p/a8e150f0e569 参考文章二&#xff1a…

利用MQ事务消息实现分布式事务

MQ事务消息使用场景 消息队列中的“事务”&#xff0c;主要解决的是消息生产者和消息消费者的数据一致性问题。 拿我们熟悉的电商来举个例子。一般来说&#xff0c;用户在电商 APP 上购物时&#xff0c;先把商品加到购物车里&#xff0c;然后几件商品一起下单&#xff0c;最后…

为游客提供完美旅程:携程集团携手亚马逊云科技联合创新

刚刚过去的“五一”假期&#xff0c;旅游行业展现出了强劲的复苏势头。经文化和旅游部数据中心测算&#xff0c;全国国内旅游出游合计2.74亿人次&#xff0c;同比增长70.83%。 然而&#xff0c;出行前的航班高铁订票、酒店商旅预订、出游行程安排&#xff0c;就已经让不少家庭为…

C++linux高并发服务器项目实践 day9

Clinux高并发服务器项目实践 day9 信号集信号集相关函数以下信号集相关的函数都是对自定义的信号集进行操作sighandler_t函数sigaction函数 SIGCHLD信号共享内存共享内存使用步骤共享内存操作函数 信号集 许多信号相关的系统调用都需要能表示一组不同的信号&#xff0c;多个信…

深度思考:在 AI 时代,你会被放大一千倍的能力是什么?

Datawhale干货 作者&#xff1a;艾芙&#xff0c;复旦大学&#xff0c;百姓AI教育负责人 前言 大家晚上好&#xff0c;我是艾芙&#xff0c;百姓 AI 的 AI 教育负责人。 先做一下自我介绍&#xff0c;我是一个在技术圈和教育圈反复横跳的斜杠中年了。大约在 5 年前&#xff0c…

C++格式输入输出

&#x1f436;博主主页&#xff1a;ᰔᩚ. 一怀明月ꦿ ❤️‍&#x1f525;专栏系列&#xff1a;线性代数&#xff0c;C初学者入门训练&#xff0c;题解C&#xff0c;C的使用文章&#xff0c;「初学」C&#xff0c;数据结构 &#x1f525;座右铭&#xff1a;“不要等到什么都没…

常用的数据中心部署架构

说起数据中心&#xff0c;相信大家并不陌生。随着互联网行业的蓬勃发展&#xff0c;大数据时代的快速到来&#xff0c;数据中心同我们的生活紧密联系&#xff0c;息息相关。我们日常生活中的各种数据几乎都存储在数据中心里&#xff0c;例如&#xff1a;手机照片的云端备份、放…

Python小姿势 - # Python相关技术知识点

Python相关技术知识点 标题 在Python中如何处理文件 如果你要处理文件&#xff0c;那么在Python中你需要使用到os模块中的一些方法。 首先&#xff0c;你需要使用os.path.exists方法来判断文件是否存在&#xff1a; python if os.path.exists(file.txt): print(文件存在) else:…

asp.net企业员工考勤管理系统

企业员工管理系统主要是为企业内部管理员工使用的&#xff0c;主要功能分为员工和管理员两部分&#xff0c;主要的功能有用户登录&#xff0c;管理员信息管理&#xff0c;公告信息管理&#xff0c;文件审批管理&#xff0c;员工信息管理&#xff0c;工资信息管理&#xff0c;奖…

全景丨0基础学习VR全景制作,平台篇第19章:热点功能-文本

大家好&#xff0c;欢迎观看蛙色VR官方——后台使用系列课程&#xff01; 功能说明 应用场景 热点&#xff0c;指在全景作品中添加各种类型图标的按钮&#xff0c;引导用户通过按钮产生更多的交互&#xff0c;增加用户的多元化体验。 文本热点&#xff0c;即点击热点后会弹出…

一顿饭的事儿,搞懂了Linux5种IO模型

大家好&#xff0c;我是老三&#xff0c;人生有三大难题&#xff0c;事业、爱情&#xff0c;和 ——这顿吃什么&#xff01; 人在家中躺&#xff0c;肚子饿得响&#xff0c;又到了不得不吃的时候&#xff0c;这顿饭该怎么吃&#xff1f;吃什么呢&#xff1f; Linux里有五种I…

【笔记】【HTTP】《图解HTTP》第1章 了解Web及网络基础

前言 有输入就要有产出&#xff0c;该笔记是本人看完《图解HTTP》后对每章涉及到的知识进行汇总博客将会已书的每章为一篇发布&#xff0c;下一篇博客发布时间不确定笔记中有些个人理解后整理的笔记&#xff0c;可能有所偏差&#xff0c;也恳请读者帮忙指出&#xff0c;谢谢。…

在Notion AI 中轻松打造您的AI私人助理,提供卓越的工作体验

大家好&#xff0c;我是瓜叔。 相信平时喜欢做笔记的人对notion 选应该不陌生近年来越来越多人开始把notion 选当做他们的主力笔记软件。 我自己也用了约4年的时间。如果你也是notion的爱好者但还不知道notion AI是什么。那这篇文章&#xff0c;我会分享我是如何实际操作使用技…