信号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的配置 虚拟机配…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
