信号signal编程测试
信号会打断系统调用,慎用,就是用的时候测一测。
下面是信号的基础测试
信号
信号(signal)机制是UNIX系统中最为古老的进程之间的通信机制。它用于在一个或多个进程之间传递异步信号。信号可以由各种异步事件产生,例如键盘中断等。Shell也可以使用信号将作业控制命令传递给它的子进程。
Linux系统中定义了一系列的信号,这些信号可以由内核产生,也可以由系统中的其他进程产生,只要这些进程有足够的权限。可以使用kill命令(kill -l)在机器上列出所有的信号,如下所示:
lkmao@ubuntu:~$ kill -l1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP6) 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()函数用于截取系统的信号,对此信号挂接用户自己的处理函数。其原型如下:
NAMEsignal - ANSI C signal handlingSYNOPSIS#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 = 2sig_func:25 -- SIGINT
kill函数和raise函数
NAMEkill - send signal to a processSYNOPSIS#include <sys/types.h>#include <signal.h>int kill(pid_t pid, int sig);
NAMEraise - send a signal to the callerSYNOPSIS#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 = 2sig_func:27 -- SIGINT count = 1
sig_func:17 -- signo = 2sig_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
小结
相关文章:
信号signal编程测试
信号会打断系统调用,慎用,就是用的时候测一测。 下面是信号的基础测试 信号 信号(signal)机制是UNIX系统中最为古老的进程之间的通信机制。它用于在一个或多个进程之间传递异步信号。信号可以由各种异步事件产生,例如…...
Linux学习记录——이십삼 进程信号(2)
文章目录 1、可重入函数2、volatile关键字3、如何理解编译器的优化4、SIGCHLD信号 1、可重入函数 两个执行流都执行一个函数时,这个函数就被重入了。比如同一个函数insert,在main中执行时,这个进程时间片到了,嵌入了内核…...
Revit中如何创建曲面嵌板及一键成板
一、Revit中如何创建曲面嵌板 在我们的绘图过程中可能会遇见一些曲面形状,而我们的常规嵌板没办法满足我们绘制的要求,我们今天学习如何在revit中绘制曲面嵌板。 1.新建“自适应公制常规模型”族,创建4个点图元并为其使用自适应。 2.在相同的…...
STM32F4_DHT11数字温湿度传感器
目录 前言 1. DHT11简介 2. DHT11数据结构 3. DHT11的传输时序 3.1 DHT11开始发送数据流程 3.2 主机复位信号和DHT11响应信号 3.3 数字 “0” 信号表示方法 3.4 数字 “1” 信号表示方法 4. 硬件分析 5. 实验程序详解 5.1 main.c 5.2 DHT11.c 5.3 DHT11.h 前言 DH…...
WiFi(Wireless Fidelity)基础(十一)
目录 一、基本介绍(Introduction) 二、进化发展(Evolution) 三、PHY帧((PHY Frame ) 四、MAC帧(MAC Frame ) 五、协议(Protocol) 六、安全&#x…...
操作系统—— 精髓与设计原理--期末复习
一、计算机系统概述 1、基本构成 计算机有四个主要的结构化部件: ①处理器(Processor):控制计算机的操作,执行数据处理功能。当只有一个处理器时,它通常指中央处理器(CPU) ②内存…...
每天一道算法练习题--Day21 第一章 --算法专题 --- ----------位运算
我这里总结了几道位运算的题目分享给大家,分别是 136 和 137, 260 和 645, 总共加起来四道题。 四道题全部都是位运算的套路,如果你想练习位运算的话,不要错过哦~~ 前菜 开始之前我们先了解下…...
D1. LuoTianyi and the Floating Islands (Easy Version)(树形dp)
Problem - D1 - Codeforces 这是问题的简化版本。唯一的区别在于在该版本中k≤min(n,3)。只有在两个版本的问题都解决后,才能进行黑客攻击。 琴音和漂浮的岛屿。 洛天依现在生活在一个有n个漂浮岛屿的世界里。这些漂浮岛屿由n−1个无向航线连接,任意两个…...
rk3588移植ubuntu server
ubuntu server 18.04 arm版本. 1、使用qemu运行 安装qemu-system-aarch64 sudo apt install -y qemu-system-arm 2、下载ubuntu server Index of /releases/18.04.3 3、创建虚拟磁盘 qemu-img create ubuntuimg.img 40G 4、创建虚拟机 弹出界面,直接回车选…...
如何更好地刷力扣
之前刷力扣是一口气看很多题目,打算时不时看一会题解,逐渐熟悉套路,争取背过,最后就可以写出来了。我个人是背知识比较喜欢这种方法,但后来发现根本不适用 算法题本身就比较复杂,不经过实际写代码中的思考…...
上采样和下采样
首先,谈谈不平衡数据集。不平衡数据集指的是训练数据中不同类别的样本数量差别较大的情况。在这种情况下,模型容易出现偏差,导致模型对数量较少的类别预测效果不佳。 为了解决这个问题,可以使用上采样和下采样等方法来调整数据集…...
小猪,信息论与我们的生活
前言 动态规划是大家都熟悉与陌生的知识,非常灵活多变,我自己也不敢说自己掌握了,今天给大家介绍一道题,不仅局限于动态规划做题,还会上升到信息论,乃至于启发自己认知世界的角度 因为比较难,本…...
【鸿蒙应用ArkTS开发系列】- http网络库使用讲解和封装
目录 前言http网络库组件介绍http网络库封装创建Har Module创建RequestOption 配置类创建HttpCore核心类创建HttpManager核心类对外组件导出添加网络权限 http网络库依赖和使用依赖http网络库(httpLibrary)使用http网络库(httpLibrary&#x…...
【Java零基础入门篇】第 ⑥ 期 - 异常处理
博主:命运之光 专栏:Java零基础入门 学习目标 掌握异常的概念,Java中的常见异常类; 掌握Java中如何捕获和处理异常; 掌握自定义异常类及其使用; 目录 异常概述 异常体系 常见的异常 Java的异常处理机制…...
计算职工工资
目录 问题描述 程序设计 问题描述 【问题描述】 给定N个职员的信息,包括姓名、基本工资、浮动工资和支出,要求编写程序顺序输出每位职员的姓名和实发工资(实发工资=基本工资+浮动工资-支出)。 【输入形式】 输入在一行中给出正整数N。随后N行,每行给出一位职员的信息,…...
2019年上半年软件设计师下午试题
试题四(共 15 分) 阅读下列说明和 C 代码,回答问题 1 至 3,将解答写在答题纸的对应栏内 【说明】 n 皇后问题描述为:在一个 n*n 的棋盘上摆放 n 个皇后,要求任意两个皇后不能冲突, 即任意两个皇后不在同一行、同一列或者同一斜…...
IS200TPROH1BCB用于工业应用和电力分配等。高压型隔离开关用于变电站
IS200TPROH1BCB用于工业应用和电力分配等。高压型隔离开关用于变电站 什么是隔离器,它与断路器有何不同 什么是隔离器,为什么要使用隔离器 隔离器是一种开关装置,它可以手动或自动操作,隔离一部分电能。隔离器可用于在无负载情…...
【MySql】数据库 select 进阶
数据库 数据库表的设计ER 关系图三大范式 聚合函数与分组查询聚合函数 (count、sum、avg、max、min)分组查询 group by fields....having....(条件) 多表联查内连接外连接(左连接,右连接)自连接子查询合并查询 UNION 数据库表的设计 ER 关系…...
CVPR 2023 | VoxelNeXt实现全稀疏3D检测跟踪,还能结合Seg Anything
在本文中,研究者提出了一个完全稀疏且以体素为基础的3D物体检测和跟踪框架VoxelNeXt。它采用简单的技术,运行快速,没有太多额外的成本,并且可以在没有NMS后处理的情况下以优雅的方式工作。VoxelNeXt在大规模数据集nuScenes、Waymo…...
本地使用3台centos7虚拟机搭建K8S集群教程
第一步 准备3台centos7虚拟机 3台虚拟机与主机的网络模式都是桥接的模式,也就是他们都是一台独立的“主机” (1)kebe-master的配置 虚拟机配置: 网络配置: (2)kebe-node1的配置 虚拟机配…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
