当前位置: 首页 > news >正文

linux万字图文学习进程信号

1. 信号概念

信号是进程之间事件异步通知的一种方式,属于软中断。

1.1 linux中我们常用Ctrl+c来杀死一个前台进程

  • 1. Ctrl-C 产生的信号只能发给前台进程。一个命令后面加个&可以放到后台运行,这样Shell不必等待进程结束就可以接受新的命令,启动新的进程。
  • 2. Shell可以同时运行一个前台进程和任意多个后台进程,只有前台进程才能接到像 Ctrl-C 这种控制键产生的信号。
  • 3. 前台进程在运行过程中用户随时可能按下 Ctrl-C 而产生一个信号,也就是说该进程的用户空间代码执行到任何地方都有可能收到 SIGINT 信号而终止,所以信号相对于进程的控制流程来说是异步(Asynchronous)的。

2.常见的信号

用kill -l命令可以察看系统定义的信号列表

  • 每个信号都有一个编号和一个宏定义名称,这些宏定义可以在signal.h中找到
  • 编号34以上的是实时信号
  • 这些信号各自在什么条件下 产生,默认的处理动作是什么,在signal(7)中都有详细说明: man 7 signal

3. 信号本质

        信号是软件中断,是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。

        信号是进程间通信机制中唯一的异步通信机制,可以看作是异步通知,通知接收信号的进程有哪些事情发生了。信号机制经过POSIX实时扩展后,功能更加强大,除了基本通知功能外,还可以传递附加信息。

4. 信号来源

4.1  通过终端按键产生信号

SIGINT的默认处理动作是终止进程,SIGQUIT的默认处理动作是终止进程并且Core Dump

4.1.1 什么是Core Dump

当一个进程要异常终止时,可以选择把进程的用户空间内存数据全部 保存到磁 盘上,文件名通常是core,这叫做Core Dump。进程异常终止通常是因为有Bug,比如非法内存访问导致段错误, 事后可以用调试器检查core文件以查清错误原因,这叫做Post-mortem Debug(事后调试)。一个进程允许 产生多大的core文件取决于进程的Resource Limit(这个信息保存 在PCB中)。默认是不允许产生core文件的, 因为core文件中可能包含用户密码等敏感信息,不安全。

在开发调试阶段可以用ulimit命令改变这个限制,允许 产生core文件。 首先用ulimit命令改变Shell进程的Resource Limit $ ulimit -c 1024 允许core文件最大为1024K

        

 

4.1.2终端按键的信号捕捉 

#include <stdio.h>
#include <signal.h>
int count = 0;
void handler(int sig)
{printf("the catched count is %d  ",++count);printf("catch a sig : %d\n", sig);
}
int main()
{signal(2, handler); // 信号是可以被自定义捕捉的,siganl函数就是来进行信号捕捉的while (1);return 0;
}

4.2. 调用系统函数向进程发信号

常用的kill 还有pkill和killall等

kill命令是调用kill函数实现的。kill函数可以给一个指定的进程发送指定的信号。raise函数可以给当前进程发送指定 的信号(自己给自己发信号)。

#include <signal.h>
int kill(pid_t pid, int signo);
int raise(int signo);
这两个函数都是成功返回0,错误返回-1。#include <stdlib.h>
void abort(void);
就像exit函数一样,abort函数总是会成功的,所以没有返回值。
abort函数使当前进程接收到信号而异常终止。

4.3  由软件条件产生信号

SIGPIPE是一种由软件条件产生的信号,在管道中读端被关闭了,写端一直写

Broken pipe: write to pipe with no readers.
管道破裂。这个信号通常在进程间通信产生,比如采用FIFO(管道)通信的两个进程,
读管道没打开或者意外终止就往管道写,
写进程会收到SIGPIPE信号。此外用Socket通信的两个进程,
写进程在写Socket的时候,读进程已经终止。
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
调用alarm函数可以设定一个闹钟,也就是告诉内核在seconds秒之后给当前进程发SIGALRM信号, 该信号的默认处理动作是终止当前进程。
可以重复设置,新的会覆盖旧的并返回上次闹钟剩余的时间,可以设置为0,意思就是取消闹钟,并返回上次闹钟剩余的时间

4.4 硬件异常产生信号

硬件异常被硬件以某种方式被硬件检测到并通知内核,然后内核向当前进程发送适当的信号。例如当前进程执行了除以0的指令,CPU的运算单元会产生异常,内核将这个异常解释 为SIGFPE信号发送给进程。再比如当前进程访问了非法内存地址(野指针),MMU会产生异常,内核将这个异常解释为SIGSEGV信号发送给进程。

4.4.1 硬件异常产生信号的捕获

并且硬件异常后程序将并不会继续向下执行

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
int count = 0;
int count2=0;
void handler(int sig)
{printf("the catched count is %d count2:%d ",++count,count2);printf("catch a sig : %d\n", sig);
}
int main()
{signal(11, handler); // 信号是可以被自定义捕捉的,siganl函数就是来进行信号捕捉的while (1){sleep(1);count2++;int *p=NULL;*p=100;}return 0;
}

5. 信号的分类

1、可靠信号与不可靠信号

不可靠信号:

Linux信号机制基本上是从Unix系统中继承过来的。早期Unix系统中的信号机制比较简单和原始,后来在实践中暴露出一些问题,因此,把那些建立在早期机制上的信号叫做"不可靠信号",信号值小于SIGRTMIN(Red hat 7.2中,SIGRTMIN=32,SIGRTMAX=63)的信号都是不可靠信号

不可靠信号主要的问题是:

  • 进程每次处理信号后,就将对信号的响应设置为默认动作。在某些情况下,将导致对信号的错误处理;因此,用户如果不希望这样的操作,那么就要在信号处理函数结尾再一次调用signal(),重新安装该信号。
  • 信号可能丢失,后面将对此详细阐述。 如果在进程对某个信号进行处理时,这个信号发生多次,对后到来的这类信号不排队,那么仅传送该信号一次,即发生了信号丢失。
    因此,早期unix下的不可靠信号主要指的是进程可能对信号做出错误的反应以及信号可能丢失。

Linux支持不可靠信号,但是对不可靠信号机制做了改进:在调用完信号处理函数后,不必重新调用该信号的安装函数(信号安装函数是在可靠机制上的实现)。因此,Linux下的不可靠信号问题主要指的是信号可能丢失

可靠信号

信号值位于SIGRTMIN和SIGRTMAX之间的信号都是可靠信号,可靠信号克服了信号可能丢失的问题Linux在支持新版本的信号安装函数sigation()以及信号发送函数sigqueue()的同时,仍然支持早期的signal()信号安装函数,支持信号发送函数kill()。

       注:不要有这样的误解:由sigqueue()发送、sigaction安装的信号就是可靠的。事实上,可靠信号是指后来添加的新信号(信号值位于SIGRTMIN及SIGRTMAX之间);不可靠信号是信号值小于SIGRTMIN的信号信号的可靠与不可靠只与信号值有关,与信号的发送及安装函数无关。目前linux中的signal()是通过sigation()函数实现的,因此,即使通过signal()安装的信号,在信号处理函数的结尾也不必再调用一次信号安装函数。同时,由signal()安装的实时信号支持排队,同样不会丢失。

       对于目前linux的两个信号安装函数:signal()及sigaction()来说,它们都不能把SIGRTMIN以前的信号变成可靠信号(都不支持排队,仍有可能丢失,仍然是不可靠信号),而且对SIGRTMIN以后的信号都支持排队。这两个函数的最大区别在于,经过sigaction安装的信号都能传递信息给信号处理函数(对所有信号这一点都成立),而经过signal安装的信号却不能向信号处理函数传递信息。对于信号发送函数来说也是一样的。

6. 信号处理常见方式

  • 1. 忽略此信号。
  • 2. 执行该信号的默认处理动作。
  • 3. 提供一个信号处理函数,要求内核在处理该信号时切换到用户态执行这个处理函数,这种方式称为捕捉 (Catch)一个信号。

7. 信号集操作函数

7.1 信号一些相关概念

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

7.2 信号在内核中的表示

  • 每个信号都有两个标志位分别表示阻塞(block)和未决(pending),还有一个函数指针表示处理动作。信号产生时,内核在进程控制块中设置该信号的未决标志,直到信号递达才清除该标志。在上图的例子中,SIGHUP信号未阻塞也未产生过,当它递达时执行默认处理动作。
  • SIGINT信号产生过,但正在被阻塞,所以暂时不能递达。虽然它的处理动作是忽略,但在没有解除阻塞之前不能忽略这个信号,因为进程仍有机会改变处理动作之后再解除阻塞。
  • SIGQUIT信号未产生过,一旦产生SIGQUIT信号将被阻塞,它的处理动作是用户自定义函数sighandler。 如果在进程解除对某信号的阻塞之前这种信号产生过多次,将如何处理?POSIX.1允许系统递送该信号一次或多次。Linux是这样实现的:常规信号在递达之前产生多次只计一次,而实时信号在递达之前产生多次可以依次放在一个队列里。注意此处不讨论实时信号。 

7.3 sigset_t

从上图来看,每个信号只有一个bit的未决标志,非0即1,不记录该信号产生了多少次,阻塞标志也是这样表示的。 因此,未决和阻塞标志可以用相同的数据类型sigset_t来存储,sigset_t称为信号集,这个类型可以表示每个信号 的“有效”或“无效”状态,在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞,而在未决信号集中“有效”和“无效”的含义是该信号是否处于未决状态。

阻塞信号集也叫做当 前进程的信号屏蔽字(Signal Mask),这里的“屏蔽”应该理解为阻塞而不是忽略。

7.4 信号集操作函数

sigset_t类型对于每种信号用一个bit表示“有效”或“无效”状态,至于这个类型内部如何存储这些bit则依赖于系统 实现,从使用者的角度是不必关心的,使用者应该调用以下函数来操作sigset_ t变量,而不应该对它的内部数据做 任何解释,比如用printf直接打印sigset_t变量是没有意义的

#include <signal.h>
int sigemptyset(sigset_t *set);//置空
int sigfillset(sigset_t *set);//置满
int sigaddset (sigset_t *set, int signo);//添加信号到信号集
int sigdelset(sigset_t *set, int signo);//在信号集中删除指定信号
int sigismember(const sigset_t *set, int signo); //在信号集查找是否有该信号

这四个函数都是成功返回0,出错返回-1。sigismember是一个布尔函数,用于判断一个信号集的有效信号中是否包含 某种 信号,若包含则返回1,不包含则返回0,出错返回-1。


 

7.5 调用函数sigprocmask可以读取或更改进程的信号屏蔽字(阻塞信号集)。

7.6 sigpending

#include <signal.h>
sigpending
读取当前进程的未决信号集,通过set参数传出。调用成功则返回0,出错则返回-1。 

 7.7 信号阻塞时未决信号的打印 

#include<iostream>
#include<signal.h>
#include<unistd.h>using namespace std;
void my_printf_sig(sigset_t* a){for(int i=0;i<65;i++){if(sigismember(a,i)){cout<<"1";//cout<<"         "<<i<<"**********";}else{cout<<"0";}}
}int main(){sigset_t block,pending;sigemptyset(&block);for(int i=0;i<65;i++){//将所有的信号都屏蔽了,但是kill -9 还是可以生效。sigaddset(&block,i);}sigprocmask(SIG_BLOCK,&block,NULL);while(1){sigpending(&pending);my_printf_sig(&pending);cout<<endl;sleep(1);cout<<"my_pid is"<<getpid()<<endl;}
}

7.8 内核如何实现信号的捕捉 

如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号。由于信号处理函数的代码 是在用户空间的,处理过程比较复杂,举例如下: 用户程序注册了SIGQUIT信号的处理函数sighandler。 当前正在执行 main函数,这时发生中断或异常切换到内核态。 在中断处理完毕后要返回用户态的main函数之前检查到有信号 SIGQUIT递达。 内核决定返回用户态后不是恢复main函数的上下文继续执行,而是执行sighandler函 数,sighandler 和main函数使用不同的堆栈空间,它们之间不存在调用和被调用的关系,是 两个独立的控制流程。 sighandler函数返 回后自动执行特殊的系统调用sigreturn再次进入内核态。 如果没有新的信号要递达,这次再返回用户态就是恢复 main函数的上下文继续执行了。

7.9 sigaction

7.9.1 siaction的定义 

  • sa_handler 是一个函数指针,指定信号处理函数,这里除可以是咱们自定义的处理函数外,还可以为SIG_DFL(采用默认的处理方式)或SIG_IGN(忽略信号)。它的处理函数只有一个参数,即信号值。
  •    sa_mask 是一个信号集,它可以指定在信号处理程序执行过程中哪些信号应当被屏蔽,在调用信号捕获函数前,该信号集要加入到信号的信号屏蔽字中。
  •    sa_flags 中包含了很多标志位,是对信号进行处理的各个选择项。它的常见可选值如下表所示

8. volatile:

volatile 作用:保持内存的可见性,告知编译器,被该关键字修饰的变量,不允许被优化,对该变量 的任何操作,都必须在真实的内存中进行操作 

9. SIGCHLD信号

父进程调 用sigaction将SIGCHLD的处理动作 置为SIG_IGN,这样fork出来的子进程在终止时会自动清理掉,不 会产生僵尸进程,也不会通知父进程。系统默认的忽 略动作和用户用sigaction函数自定义的忽略 通常是没有区别的,但这是一个特例。此方法对于Linux可用,但不保证 在其它UNIX系统上都可用。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>using namespace std;void sigchld_handler(int signum)
{// 处理SIGCHLD信号,可以不需要具体的逻辑// 在这个示例中,我们可以仅仅打印一条消息printf("Received SIGCHLD signal\n");
}int main()
{// 设置SIGCHLD的处理动作为SIG_IGN// struct sigaction sa;// sa.sa_handler = SIG_IGN;// sigemptyset(&sa.sa_mask);// sa.sa_flags = 0;// sigaction(SIGCHLD, &sa, NULL);pid_t pid = fork();if (pid == 0){// 子进程// printf("Child process\n");cout << "child process pid is : " << getpid() << endl;// do something...sleep(30);cout << "child exit" << endl;exit(0);}else if (pid > 0){// 父进程// printf("Parent process\n");cout << "parent process pid is : " << getpid() << endl;// 等待子进程结束sleep(100); // 等待足够长的时间,以确保子进程已经结束printf("Parent process exiting\n");}else{// fork失败printf("Fork failed\n");return 1;}return 0;
}// while :; do ps axj|head -1&& ps axj |grep sig_ignore|grep -v grep;sleep 1; done;

思考总结:

所有信号产生,最终都要有OS来进行执行,为什么?OS是进程的管理者 信号的处理是否是立即处理的?在合适的时候 信号如果不是被立即处理,那么信号是否需要暂时被进程记录下来?记录在哪里最合适呢? 
在Linux中,如果信号在接收时不能立即处理,进程通常需要将信号记录下来以便稍后处理。Linux使用信号队列来存储接收到但尚未处理的信号。
每个Linux进程都有一个信号处理器表,用于存储信号处理程序的地址。当进程收到一个信号时,操作系统会根据进程的信号处理器表确定应该执行哪个信号处理程序。
在信号处理期间,Linux使用信号屏蔽字和挂起信号队列来处理挂起的信号。挂起信号队列是内核中的数据结构,用于存储挂起的信号。当进程正在处理信号时,其他同类信号可能会被挂起,并在当前信号处理程序完成后按照一定的优先级顺序逐个处理。
挂起信号队列位于内核中,因此信号被记录在内核的上下文中。这种设计可以保证在进程切换时仍然可以正确处理挂起信号。
最合适记录信号的位置是在Linux内核的信号挂起队列中。这样,在进程重新调度执行时,操作系统可以检查信号挂起队列并将挂起的信号传递给进程进行处理。
需要注意的是,Linux对于不同类型的信号有不同的处理机制。一些信号(如SIGSTOP和SIGKILL)不能被挂起,它们会立即中断进程的执行。但大多数其他信号可以挂起并在适当的时候处理。
总之,Linux使用信号挂起队列来记录未立即处理的信号。这种机制确保了信号的顺序和正确处理,同时保证了信号的可靠交付。一个进程在没有收到信号的时候,能否能知道,自己应该对合法信号作何处理呢?
能够,信号的默认处理动作在linux的内核中 如何理解OS向进程发送信号?
理解操作系统(OS)向进程发送信号可以从两个方面来考虑:1.异步事件通知:操作系统可以在特定事件发生时向进程发送信号,以通知进程发生了某些异步事件。这些事件可能包括:用户按下特定的键盘组合,例如Ctrl+C,触发SIGINT信号。
定时器到期,触发SIGALRM信号。
子进程终止,触发SIGCHLD信号。
硬件故障,例如除零错误,触发SIGFPE信号。
当这些事件发生时,操作系统会向目标进程发送相应的信号,以便进程可以作出相应的反应。这可以通过操作系统的信号传递机制实现,如Linux中的信号队列。2.进程间通信:除了异步事件通知外,操作系统还可以通过信号在进程之间进行通信。进程可以向其他进程发送信号以触发特定的行为或进行协调。这可以用于以下情况:进程间的同步和通知:一个进程可以向另一个进程发送信号来通知某个事件的发生,以便目标进程进行相应的处理。例如,父进程向子进程发送信号以指示某个任务已完成。
进程控制和管理:某些信号可以用于控制和管理进程。例如,通过SIGKILL信号可以强制终止一个进程,通过SIGSTOP信号可以暂停一个进程的执行。
信号处理程序的使用:进程可以注册自定义的信号处理程序,当接收到特定信号时,操作系统会调用该处理程序来执行特定的操作。这样进程就可以利用信号处理程序来处理特定事件或执行自定义逻辑。总体而言,操作系统通过向进程发送信号,实现了事件通知、进程间通信和进程控制等功能。这为进程提供了一种有效的方式来与操作系统进行交互,并实现合适的响应和协作。能否描述一下完整的发送处理过程?
当进程发送信号时,它调用kill()、raise()或发送信号的相关系统调用。内核接收到信号后,会检查接收进程的权限和状态。如果接收进程具有对该信号的处理程序,并且信号未被阻塞,则内核会将信号递交给接收进程的信号处理程序。如果接收进程没有对信号进行处理或信号被阻塞,则内核采取默认的行为,如终止进程(SIGKILL)或忽略该信号(SIGIGN)。整个过程涉及信号发送、接收进程状态检查以及信号的处理或默认行为的执行。
详细版:
发送信号:信号源:信号可以来自多个源头,例如操作系统触发的异步事件、其他进程的信号发送、硬件中断等。
信号发送:信号源通过系统调用(如kill())或其他适当的机制向目标进程发送信号。发送信号时,需要指定目标进程的标识符,如进程ID(PID)或进程组ID(PGID)。
接收信号:目标进程:操作系统在目标进程上选择一个合适的执行点来接收信号。这通常是在进程的用户态代码执行时进行检查。
信号递交检查:目标进程在执行期间会定期进行对信号的检查,以确定是否有新的信号需要处理。这个过程通常是由操作系统提供的信号传递机制完成的。
信号处理:默认行为:如果进程未注册特定信号的处理程序,或者没有明确指定默认操作的信号,操作系统将使用默认的信号处理行为来处理信号。这可能包括终止进程、忽略信号或者进行其他特定的操作。
自定义处理程序:进程可以使用系统调用(如signal()或sigaction())注册自定义的信号处理程序。当信号到达时,操作系统会调用相应的信号处理程序来执行特定的操作或指令。
信号处理程序执行:信号处理程序执行在进程的上下文中,可以执行特定的代码逻辑来响应信号。信号处理程序可以进行一系列操作,如记录日志、修改进程状态、发送其他信号等。
注意,由于信号处理程序在进程的执行上下文中执行,它必须是轻量级且可靠的。一些操作(如堆内存分配和长时间的计算)可能不适合在信号处理程序中执行。
信号处理完成:处理结果:信号处理程序完成后,进程可以根据需要执行后续操作,并继续执行原始代码逻辑。
信号状态更新:处理完信号后,操作系统将清除信号的挂起状态,并允许其他信号继续递交给进程。
这是一个基本的信号发送和处理过程的概述。具体的实现细节和行为取决于操作系统和编程语言的规范。不同的操作系统和编程语言可能有自己的信号处理机制和可调整的参数。因此,在具体的应用环境中,还需要参考相关的文档和规范来了解操作系统的具体行为和限制挂起的信号是指在信号处理程序执行期间接收到的但还没有被处理的信号。当一个进程正在执行信号处理程序时,如果这个进程收到了其他信号(除了一些特定的硬件相关信号),这些新的信号将会被挂起,即暂时不会被递交给进程。相反,这些挂起的信号会等待当前正在执行的信号处理程序完成后再进行递交。这种机制保证了信号处理程序的一致性和可靠性。

相关文章:

linux万字图文学习进程信号

1. 信号概念 信号是进程之间事件异步通知的一种方式&#xff0c;属于软中断。 1.1 linux中我们常用Ctrlc来杀死一个前台进程 1. Ctrl-C 产生的信号只能发给前台进程。一个命令后面加个&可以放到后台运行,这样Shell不必等待进程结束就可以接受新的命令,启动新的进程。2. S…...

DataX实现Mysql与ElasticSearch(ES)数据同步

文章目录 一、Linux环境要求二、准备工作2.1 Linux安装jdk2.2 linux安装python2.3 下载DataX&#xff1a; 三、DataX压缩包导入&#xff0c;解压缩四、编写同步Job五、执行Job六、定时更新6.1 创建定时任务6.2 提交定时任务6.3 查看定时任务 七、增量更新思路 一、Linux环境要求…...

第二章 进程与线程 十、调度算法1(先来先服务、短作业优先、最高响应比优先)

目录 一、先来先服务算法 1、算法思想 2、算法规则 3、用于作业/进程调度 4、是否可抢占? 5、优缺点 优点&#xff1a; 缺点&#xff1a; 6、是否会导致饥饿 7、例子 二、短作业优先算法 1、算法思想 2、算法规则 3、用于作业/进程调度 4、是否可抢占? 5、优缺…...

windows平台 git bash使用

打开所在需要git管理的目录,鼠标右键open Git BASH here 这样就直接进来,不需要windows dos窗口下麻烦的切路径&#xff0c;windows和linux 路径方向不一致 (\ /) 然后git init 建立本地仓库,接下来就是git相关的操作了. 图形化界面查看 打开所在需要git管理的目录,鼠标右键…...

Linux系统之安装uptime-kuma服务器监控面板

Linux系统之安装uptime-kuma服务器监控面板 一、uptime-kuma介绍1.1 uptime-kuma简介1.2 uptime-kuma特点 二、本次实践环境介绍2.1 环境规划2.2 本次实践介绍2.3 环境要求 三、检查本地环境3.1 检查本地操作系统版本3.2 检查系统内核版本3.3 检查系统是否安装Node.js 四、部署…...

计算机组成原理——基础入门总结(一)

本帖更新一些关于计算机组成原理的重点内容。由于博主考研时并不会考这门课&#xff0c;但是考虑到操作系统中又很多重要晦涩的概念涉及很多诸如内存、存储器、磁盘、cpu乃至各种寄存器的知识&#xff0c;此处挑选一些核心的内容总结复盘一遍——实现声明&#xff1a;本帖的内容…...

批量获取CSDN文章对文章质量分进行检测,有助于优化文章质量

&#x1f4da;目录 ⚙️简介✨分析获取步骤⛳获取文章列表☘️前期准备✨ 接口解析⚡️ 获取文章的接口 ☄️文章质量分接口⭐接口分析 ⌛代码实现&#xff1a;⚓核心代码:⛵测试用例:⛴ 运行效果:☘️增加Excel导出 ✍️结束 ⚙️简介 有时候我们写文章是为了记录当下遇到的bu…...

从一到无穷大 #17 Db2 Event Store,A Purpose-Built IoT Database Engine

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 本作品 (李兆龙 博文, 由 李兆龙 创作)&#xff0c;由 李兆龙 确认&#xff0c;转载请注明版权。 文章目录 引言Architectural overviewData format and meta-dataEnsuring fast ingestionMulti…...

9月16日,每日信息差

今天是2023年09月16日&#xff0c;以下是为您准备的15条信息差 第一、天猫超市首单“茅小凌”已由菜鸟送达&#xff0c;首单已由菜鸟供应链完成履约&#xff0c;18分钟送达消费者手中 第二、软银考虑对OpenAI进行投资。此外&#xff0c;软银还初步拟收购英国人工智能芯片制造…...

准备篇(二)Python 教程

Part 1 Python 基础语法区分输入与输出注释文本列表if 语句for 语句range() 函数走向编程的第一个例子Part 2 函数 和 数据结构函数数据结构del 语句列表详解元组集合字典循环的技巧Part 3 输入与输出读写文件打开文件 open()读文件写文件...

HTML+CSS画一个卡通中秋月饼

HTMLCSS画一个卡通中秋月饼&#x1f96e;&#x1f96e;&#x1f96e; 中秋活动水个文章 整个divcss实现个月饼&#xff0c;给前端初学者一个练手的demo 效果图 思路 HTMl 先来个轮廓画脸上的东西&#xff1a;眼睛、眉毛、腮红、嘴巴眼睛丰富下瞳孔画20个花瓣 CSS 轮廓是要外…...

echarts的折线图,在点击图例后,提示出现变化,不报错。tooltip的formatter怎么写

在点击图例的年后&#xff0c;提示框会相应的变化&#xff0c;多选和单选都会响应变化。tooptip的重度在formatter tooltip:{show:true,trigger:"axis",alwaysShowContent:true,triggerOn:"mousemove",textStyle:{color:"#fff"},backgroundColor…...

C++中的auto是一个关键字,用于在编译时自动推导变量的类型

C中的auto是一个关键字&#xff0c;用于在编译时自动推导变量的类型。通过使用auto关键字&#xff0c;编译器可以根据变量的初始化表达式来确定其类型&#xff0c;从而省略了显式地指定类型的步骤。 使用auto关键字声明的变量必须在定义时进行初始化&#xff0c;以便编译器可以…...

VUE build:gulp打包:测试、正式环境

目录 项目结构 Gulp VUE使用Gulp Vue安装Gulp Vue定义Gulp.js package.json build文件夹 config文件夹 static-config文件夹 项目结构 Gulp Gulp是一个自动化构建工具&#xff0c;可以帮助前端开发者通过自动化任务来管理工作流程。Gulp使用Node.js的代码编写&#xff…...

1.使用turtle换一个五环2.设计这样一个程序:输入一个数字 判断它是不是一个质数

1.使用turtle换一个五环 import turtle turtle.pensize(15) turtle.penup() turtle.color(blue) turtle.goto(-150,-35) turtle.pendown() turtle.circle(60) turtle.penup() turtle.color(black) turtle.goto(0,-35) turtle.pendown() turtle.circle(60) turtle.penup() turtl…...

C语言希尔排序

希尔排序&#xff08;Shell Sort&#xff09;是插入排序的一种&#xff0c;也称缩小增量排序&#xff0c;是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。 希尔排序的基本思想是&#xff1a;先将整个待排序的记录序列分割成为若干子序列&#xff08;由…...

KubeSphere 在互联网医疗行业的应用实践

作者&#xff1a;宇轩辞白&#xff0c;运维研发工程师&#xff0c;目前专注于云原生、Kubernetes、容器、Linux、运维自动化等领域。 前言 2020 年我国互联网医疗企业迎来了“爆发元年”&#xff0c;越来越多居民在家隔离期间不方便去医院看诊&#xff0c;只好采取在线诊疗的手…...

物联网:用python调入机器学习分析物联网数据入侵检测模块

要使用Python调用机器学习分析物联网数据入侵检测模块&#xff0c;您需要以下步骤&#xff1a; 安装Python和相关的机器学习库&#xff0c;如scikit-learn、pandas、numpy等。您可以使用pip命令来安装这些库。 准备输入数据。这些数据可以是来自物联网设备的原始数据&#xff…...

使用scss简化媒体查询

在进行媒体查询的编写的时候&#xff0c;我们可以利用scss与与编译器&#xff0c;通过include混入的方式对代码进行简化&#xff0c;从而大大提高了代码的可维护性&#xff0c;也减少了代码的编写量&#xff0c;废话不多说&#xff0c;直接上代码&#xff1a; // 断点列表 相当…...

win部署CRM

win部署crm&#xff09; 1.phpstudy2.composer3.代码4.其他配置 周末锴哥让我帮他部署了一个CRM&#xff0c;写个教程&#xff0c;方便之后他用。锴哥用的是 NxCrm&#xff0c;先把代码下下来。 1.phpstudy 1.首先是下载小皮面板&#xff0c;配置php的环境。这里面下载了php8…...

Linux命令200例:dip用于用户与远程主机建立通信连接

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;CSDN领军人物&#xff0c;全栈领域优质创作者✌。CSDN专家博主&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0…...

【每日一题】981. 基于时间的键值存储

981. 基于时间的键值存储 - 力扣&#xff08;LeetCode&#xff09; 设计一个基于时间的键值数据结构&#xff0c;该结构可以在不同时间戳存储对应同一个键的多个值&#xff0c;并针对特定时间戳检索键对应的值。 实现 TimeMap 类&#xff1a; TimeMap() 初始化数据结构对象void…...

IMU姿态解算,从IMU数据中计算旋转、速度、位置,IMU测量的原理

0. 预备 a. IMU测量值解释 IMU在测量时&#xff0c;得到的角速度或者加速度均是相对于地心惯性系结果&#xff0c;并且将该结果表示到Body坐标系下&#xff0c;就形成了最终的IMU输出。 记作&#xff1a; ω i b b \omega_{ib}^b ωibb​&#xff0c;表示body系相对于惯性系的…...

【Qt-17】Qt调用matlab生成的dll库

matlab生成dll库 1、matlab示例代码 function BDCube(x,y)[x,y,z] cylinder(x,y);t1 hgtransform;s1 surf(3*x,3*y,4*z,Parent,t1);grid onview(3)shading interp end 2、matlab环境配置 首先检查自己的mcc编译器是否可用&#xff0c;输出以下命令&#xff1a; &#x…...

css经典面试题(二)

文章目录 1、清除浮动2、opacity: 0、visibility: hidden、display: none 的区别3、css画一个三角形4、常见的主流浏览器前缀5、重绘与重排的区别&#xff1f;6、如何优化图片7、CSS3 中 transition 和 animation 的属性分别有哪些8、居中为什么要使用 transform&#xff08;为…...

jira搜索search issue条目rest实用脚本

官方文档链接地址&#xff1a; The Jira Cloud platform REST API 实用json请求脚本如下&#xff1a; {"fields": ["summary","status"],"jql": "project abc AND summary ~ 【%s】【coverity】 AND componentCoverity"…...

《C++ primer plus》精炼(OOP部分)——对象和类(5)

“学习是照亮心灵的火炬&#xff0c;它永不熄灭&#xff0c;永不止息。” 文章目录 类的自动和强制类型转换原始类型转换为自定义类型将自定义类型转换为原始类型 类的自动和强制类型转换 原始类型转换为自定义类型 可以用一个参数的构造函数来实现&#xff0c;例如&#xff…...

钉钉旧版服务端SDK支持异步方法的升级改造

最近项目中需要对接钉钉&#xff0c;有些钉钉 API 的访问需要使用旧版服务端 SDK 才能搞定&#xff0c;但是这个 SDK 使用的还是 .NET Framework 2.0 框架&#xff0c;不能跨平台部署&#xff0c;也不支持 async\await 的异步操作方法&#xff0c;Nuget 上也有其它用户改造的 .…...

【C语言】【数据存储】用%d打印char类型数据,猜结果是啥

题目代码如下&#xff1a; #include <stdio.h> int main() {char a -1;signed char b-1;unsigned char c-1;printf("a%d,b%d,c%d",a,b,c);return 0; }解题关键&#xff1a; 1.二进制存储&#xff1a;原码&#xff0c;反码&#xff0c;补码 互换 2.截断 3.整型…...

算法——双指针

1658. 将 x 减到 0 的最小操作数 - 力扣&#xff08;LeetCode&#xff09; 这道题的重点是&#xff0c;如何用最小的操作数&#xff0c;来使其x变为0——也可以看作是用最少的数据个数&#xff0c;来求和得到x。 ——但是我们可以知道&#xff0c;由于数据是从两端向中间取的…...

咨询网站 模板/环球网

在上次的分享中&#xff0c;介绍了模型建立与使用梯度下降法优化参数、梯度校验&#xff0c;以及一些超参数的经验。 本节课的主要内容&#xff1a; 1链式法则 2深度学习框架中链式法则 3全连接神经网络 1、链式法则 目前我们所处的阶段&#xff1a; 学习了SVM softmax两个模型…...

怎么做独立网站/网站设计制作哪家好

c2自r120之后允许用户自己添加插件 插件的目录为 info.xml files\myplugin\common.js files\myplugin\edittime.js files\myplugin\PluginIcon.ico files\myplugin\runtime.js info.xml文件主要是插件的基本信息 <?xml version"1.0" encoding"UTF-8…...

抖音关键词排名系统/百度seo查询

深入理解es6和es6标准入门哪本好Dubbo的分布式系统架构实战需要哪些步骤完成HTML如何添加水平分割线:HTML提供了修饰段落的水平分割线&#xff0c;在很多的网页布局中都可以轻松使用&#xff0c;而不需要另外作图。水平分割线的标签是单标签&#xff1a; 默认情况下只占一行。 …...

wordpress 两个导航/深圳seo优化服务

ColorPicker一款仿Photoshop取色器的Android版取色器。前言上一篇已经简单介绍了ColorPicker的核心自定义控件ColorPickerView的绘制流程。接下来我们详细解析一下ColorPickerView的监听事件相关代码。注&#xff1a;初始颜色传入在讲颜色改变监听之前&#xff0c;先来讲讲初始…...

seo网站建设是什么意思/朋友圈广告推广平台

VisualVM是一个以监控、显示本地或者远程服务器JVM工作情况&#xff0c;进行性能调优的工具。借助VisualVM&#xff0c;我们可以实现对JVM内存各个子池、CPU、垃圾收集器等方面进行监控&#xff0c;从而发现程序代码中潜在的泄露点和配置问题。 远程监控Linux JVM有两种连接方式…...

重庆做网站优化推广的公司/站长之家域名

自主操作的水下机器人可以在从研究海洋到探索其他行星的各个领域中使用。普渡大学的科学家们开发了一种移动坞站&#xff0c;它不仅可以使这些机器停下来进行充电&#xff0c;还可以同时卸载其数据&#xff0c;从而为它们提供了一种无需人工输入即可长时间运行的方式。 我们已…...