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

信号【Linux】

1、信号就算没有产生,进程也必须识别和能够处理信号,要具备处理信号的能力,信号的处理能力,属于进程内置功能的一部分
2、当进程收到一个具体的信号时,进程可能并不会立即处理这个信号,在合适的时候处理信号

3、当信号产生,到信号开始被处理,这段时间,哪些信号已经产生,进程必须知道

信号处理方式(信号递达)

信号处理方式:
1、进程内置了对信号的处理,默认动作
2、进程可以忽略信号
3、自定义动作,会更改进程内置的默认动作,比如:信号的捕捉

信号捕捉 ,会将信号的默认处理方式修改,比如一个信号本来默认处理方式是终止进程并退出进程,信号捕捉之后该信号的默认处理方式被修改,会出现只捕捉而不退出进程了

signal,修改特定进程对于信号的处理动作的

 typedef void (*sighandler_t)(int);sighandler_t signal(int signum, sighandler_t handler);

handler这个参数是自定义的动作

前后台进程

关于前后台进程:
前台进程:能获取键盘输入

后台进程:不能获取键盘输入

./myprocess & ,加了& ,就变成后台进程了

[cxq@iZwz9fjj2ssnshikw14avaZ lesson31]$ ll
total 36
-rw-rw-r-- 1 cxq cxq    90 Jul 15 22:41 Makefile
-rwxrwxr-x 1 cxq cxq 26440 Jul 15 15:31 myprocess
-rw-rw-r-- 1 cxq cxq   443 Jul 15 22:41 mysignal.cc
-rw-rw-r-- 1 cxq cxq     0 Jul 14 16:59 test.c
[cxq@iZwz9fjj2ssnshikw14avaZ lesson31]$ ./myprocess &

Linux中,一次登陆中,一个终端,一般会配上一个bash,每一个登陆,只允讲一个进程是前台进程,但是可以允许多个进程是后台进程

终端按键产生信号

ctrl +c为什么能够杀掉我们前台进程?

ctrl +c产生的信号只能发给前台进程, ctrl +c本质是被进程解释成为收到了信号,2号信号

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

信号的产生和我们自己的代码的运行时异步的 ,
异步:代码在运行时,信号什么时候产生是不清楚的,代码不用管信息什么时候产生,代码继续运行就可以了

ctrl +c : 2号信号

#include<iostream>
#include<stdio.h>#include <signal.h>#include<unistd.h>
using namespace std ;void myhandler(int signo)
{cout << "process get a signal: " << signo <<endl;// exit(1);
}
int main()
{
//捕捉 2号信号signal(2 , myhandler);//myhandler是函数指针//signal只需要设置一次,往后都有效//信号的产生和我们自己的代码的运行时异步的 ,异步:代码在运行时,信号什么时候产生是不清楚的,代码不用管信息什么时候产生,代码继续运行就可以了while(true){cout << "I am a crazy process : " << getpid() << endl;sleep(1);}return 0 ;
}

ctrl + : 3号信号
不是所有的信号都是可以被signal捕捉的,比如:19 (暂停进程), 9(杀死进程)

kill系统调用接口向进程发信号

kill给pid进程发sig信号

int kill(pid_t pid, int sig);
#include<iostream>
#include<stdio.h>#include <signal.h>#include<unistd.h>#include <stdlib.h>#include<string>
using namespace std ;
void Usage(string proc)
{cout << "Usage:\n\t" << proc << " signum pid\n\n";
}//   mykill signum pidint main(int argc ,char* argv[]) //命令行参数
{//告诉用户如何使用if(argc !=3){Usage(argv[0]);exit(1);}string signumStr(argv[1]);string pidStr(argv[2]);int signum = stoi(signumStr); pid_t pid = stoi(pidStr);int n =kill(pid,signum); if(n == -1){   perror("kill");exit(2);}return 0 ;
}

raise:发送一个信号给调用者

  int raise(int sig);

举例:

#include<iostream>
#include<stdio.h>#include <signal.h>#include<unistd.h>#include <stdlib.h>#include<string>
using namespace std ;
void myhandler(int signo)
{cout << "process get a signal: " << signo <<endl;//   exit(1);
}
int main()
{int cnt =5 ;signal(2,myhandler); //捕捉2号信号while (true){cout << "I am a process, pid: " << getpid() << endl;sleep(1);cnt--;if(cnt== 0) {raise(2);  //等价于 kill(getpid() , 2) }}return 0 ;
}

abort 发送6号信号和终止进程

       void abort(void);

信号产生的方式,但是无论信号如何产生,最终操作系统发送给进程,因为操作系统是进程的管理者

alarm ,设置一个闹钟

 unsigned int alarm(unsigned int seconds);

return val:
alarm 函数返回的是之前设置的定时器的剩余时间。如果之前没有设置定时器,或者定时器已经到期,返回 0。
返回的剩余时间是指在调用新的 alarm 之前,定时器还有多少秒才会发送 SIGALRM 信号。

#include <iostream>#include <unistd.h>#include <signal.h>using namespace std;
void myhandler(int signo)
{cout<<"xxxxxxxxxx"<<signo<<endl;//理解alarm的返回值int n = alarm(3);cout<<"剩余时间:"<<n<<endl;//exit(1);
}int main()
{int n = alarm(50);//alarm发送的是14号信号signal(14,myhandler);//myha ndler是一个函数指针while(1){cout << "proc is running  pid :%d" <<" "<<getpid()<< endl;sleep(1);}return 0 ;
}

打开系统的core dump (核心转储)功能,一旦进程出异常,操作系统会将进程在内存中的运行信息,给转诸到进程的当前目录,并形成core.pid文件

ulimit :显示和设置用户可以启动的进程的资源限制

[cxq@iZwz9fjj2ssnshikw14avaZ output]$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 6943
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65535
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 4096
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

打开系统的core dump (核心转储)功能,将core file size 设置为10240

[cxq@iZwz9fjj2ssnshikw14avaZ output]$ ulimit -c 10240
[cxq@iZwz9fjj2ssnshikw14avaZ output]$ ulimit -a
core file size          (blocks, -c) 10240
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 6943
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65535
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 4096
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

测试 core dump功能

#include <iostream>#include <unistd.h>#include <signal.h>#include <sys/types.h>#include <sys/wait.h>
using namespace std;
int main()
{//测试  core dump功能cout << " a = " << a << endl;pid_t id = fork();if(id==0){//childint cnt = 500;while(cnt){cout << "i am a child process, pid: " << getpid() << "cnt: " << cnt << endl;sleep(1);cnt--;}exit(0);}//father //进程等待int status =0 ;pid_t rid=waitpid(id,&status,0);//阻塞等待if(rid==id){cout << "child quit info, rid: " << rid << " exit code: " << ((status>>8)&0xFF) << " exit signal: " << (status&0x7F) <<" core dump: " << ((status>>7)&1) << endl; //  (0000 0000 ... 0001)}return 0 ;
}

在这里插入图片描述
生成的core.pid文件,可以通过gdb直接定位到出错行
在这里插入图片描述

阻塞信号

信号常见概念
1、实际执行信号的处理动作,称为信号递达(Delivery)。
例:进程内置了对信号处理的默认动作、进程可以忽略信号、还是自定义动作 这些都是信号的处理动作,都是信号递达

2、信号从产生到递达之间的状态,称为信号未决(pending)。
信号从产生到递达之前,此时信号处于位图中,此时信号处于保存状态 ,这种状态称为信号未决

3、进程可以选择阻塞(Block)某个信号。这里的阻塞可以理解为屏蔽

  • 默认情况下,所有信号都是没有被屏蔽的 , 进程可以屏蔽某些信号,在解除屏蔽之前,信号 也不会被操作系统进行递达

  • 如果进程没有收到某一个信号,也可以屏蔽这个信号

4、被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。

  • 一个信息如果被阻塞了(屏蔽),如果此时用户向进程发送了指定的信号,该信号不会被递达,直到解除了阻塞 ,也就是说阻塞了还是可以给进程发送信号,只不过信号暂时被屏蔽罢了

5阻塞和忽略是完全不同的,只要信号被阻塞就不会递达,而忽略是在递达之后的一种处理动作

  • 只要信号被阻塞就不会递达,即不会被处理,屏蔽和解决屏蔽一定是在递达之前做的
  • 忽略的本质是处理信号,忽略是信号递达的三种方式之一,忽略是在递达之后的一种处理动作
  • 阻塞可以理解为未读,忽略可以理解为已读不回

block表:.比特位的内容是1还是0,表明是否屏蔽信号
比特位的位置(第几个),表示信号的编号

pending表:
比特位的内容是1还是0,表明是否收到信号
比特位的位置(第几个),表示信号的编号
handler表:
handler表本质上是一个函数指针数组,数组的下标代表某一个信号,数组的内容代表该信号递达时的处理动作,处理动作包括默认、忽略以及自定义
block、pending和handler这三张表的每一个位置是一一对应的
在这里插入图片描述

  • 每个信号都有两个标志位分别表示阻塞(block)和未决(pending),还有一个函数指针表示处理动作。信号产生时,内核在进程控制块中设置该信号的未决标志,直到信号递达才清除该标志。在上图中,SIGHUP信号未阻塞也未产生过,当它递达时执行默认处理动作。
  • SIGINT信号产生过,但正在被阻塞,所以暂时不能递达。虽然它的处理动作是忽略,但在没有解除阻塞之前不能忽略这个信号,因为进程仍有机会在改变处理动作之后再接触阻塞。
  • SIGQUIT信号未产生过,但一旦产生SIGQUIT信号,该信号将被阻塞,它的处理动作是用户自定义函数sighandler。如果在进程解除对某信号的阻塞之前,这种信号产生过多次,POSIX.1允许系统递达该信号一次或多次。Linux是这样实现的:普通信号在递达之前产生多次只计一次,而实时信号在递达之前产生多次可以依次放在一个队列里,这里只讨论普通信号
#include <iostream>#include <unistd.h>#include <signal.h>#include <sys/types.h>#include <sys/wait.h>
using namespace std;
int main()
{//理解handler表的SIG_IGN,SIG_DFL//signal(2,SIG_IGN);//忽略2号信号signal(2,SIG_DFL);//使用2号信号的默认处理方法while(1){cout << "hello signal" << endl;sleep(1);}return  0; 
}

sigset_t

根据信号在内核中的表示方法,每个信号的未决标志只有一个比特位,非0即1,如果不记录该信号产生了多少次,那么阻塞标志也只有一个比特位。因此,未决和阻塞标志可以用相同的数据类型sigset_t来存储

在我当前的云服务器中,sigset_t类型的定义如下:(不同操作系统实现sigset_t的方案可能不同)

typedef __sigset_t sigset_t;
# define _SIGSET_NWORDS	(1024 / (8 * sizeof (unsigned long int)))
typedef struct{unsigned long int __val[_SIGSET_NWORDS];} __sigset_t;

sigset_t称为信号集,这个类型可以表示每个信号的“有效”或“无效”状态。

  • 在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞。
  • 在未决信号集中“有效”和“无效”的含义是该信号是否处于未决状态。

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

#include <signal.h>//sigemptyset、sigfillset、sigaddset和sigdelset函数都是成功返回0,出错返回-1。int sigemptyset(sigset_t *set);//初始化set所指向的信号集,使其中所有信号的对应bit清零,表示该信号集不包含任何有效信号int sigfillset(sigset_t *set);//始化set所指向的信号集,使其中所有信号的对应bit置位,表示该信号集的有效信号包括系统支持的所有信号。int sigaddset(sigset_t *set, int signum);//在set所指向的信号集中添加某种有效信号。int sigdelset(sigset_t *set, int signum);//在set所指向的信号集中删除某种有效信号。int sigismember(const sigset_t *set, int signum);  //判断在set所指向的信号集中是否包含某种信号,若包含则返回1,不包含则返回0,调用失败返回-1。

sigprocmask

sigprocmask :用于读取或更改进程的信号屏蔽字(阻塞信号集)

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

1、如果oldset是非空指针,则读取进程当前的信号屏蔽字通过oldset参数传出。
2、如果set是非空指针,则更改进程的信号屏蔽字,参数how指示如何更改。
3、如果oldset和set都是非空指针,则先将原来的信号屏蔽字备份到oldset里,然后根据set和how参数更改信号屏蔽字

how参数的可选值及其含义: 以下三个只能选一个作为how参数

  • SIG_BLOCK set包含了我们希望添加到当前信号屏蔽字的信号,相当于mask=mask|set
  • SIG_UNBLOCK set包含了我们希望从当前信号屏蔽字中解除阻塞的信号,相当于mask=mask|~set
  • SIG_SETMASK 覆盖式的设置当前信号屏蔽字为set所指向的值,相当于mask=set

return val: sigprocmask函数调用成功返回0,出错返回-1。

如果调用sigprocmask解除了对当前若干个未决信号的阻塞,则在sigprocmask函数返回前,至少将其中一个信号递达

sigpending

sigpending:用于读取进程的未决信号集,

int sigpending(sigset_t *set);

sigpending函数读取当前进程的未决信号集,并通过set参数传出。
return val :该函数调用成功返回0,出错返回-1。

1、将2号信号进行屏蔽(阻塞)。

2、使用kill命令或组合按键向进程发送2号信号。
3、此时2号信号会一直被阻塞,并一直处于pending(未决)状态。
4、使用sigpending函数获取当前进程的pending信号集进行验证
测试代码:

#include<iostream>#include <signal.h>
#include<unistd.h>
using namespace std ;void PrintPending(sigset_t & pending)
{for(int signo = 31 ;   signo>=1 ; signo--){if(sigismember(&pending , signo)  ==1)//判断在set所指向的信号集中是否包含某种信号{//存在cout << "1";}else{//不存在cout << "0";}}// cout << "\n\n";//将光标从当前位置向下移动两行cout<<endl;cout<<endl;}
int main()
{//将2号信号进行屏蔽(阻塞)。
// 使用kill命令或组合按键向进程发送2号信号。
// 此时2号信号会一直被阻塞,并一直处于pending(未决)状态。
// 使用sigpending函数获取当前进程的pending信号集进行验证
sigset_t  bset,oset ;
sigemptyset(&bset);//使bset其中所有信号的对应bit清零
sigemptyset(&oset);//使oset其中所有信号的对应bit清零sigaddset(&bset,2);//在set所指向的信号集中添加2号信号。
sigprocmask(SIG_SETMASK ,&bset, &oset);//把bset覆盖式的设置到进程的block位图中//代码走到这里,已经屏蔽2号信号了//重复打印当前进程的pendingsigset_t pending ;
int cnt =0 ;
while(true)
{// 2.1 获取int n = sigpending(&pending);if (n < 0)continue;// 2.2 打印PrintPending(pending);sleep(1);// 2.3 解除阻塞cnt ++;if(cnt ==20){cout << "unblock 2 signo" << endl;sigprocmask(SIG_SETMASK ,&oset,nullptr);//更改进程的信号屏蔽字,覆盖式的设置当前信号屏蔽字为bset所指向的值}
}return 0 ; 
}

内核态与用户态:

  • 内核态:允许访问操作系统的代码和数据,是一种权限非常高的状态。
  • 用户态:只能访问用户自己的代码和数据,是一种受监管的普通状态。

当进程从内核态返回到用户态时,进行信号的检测和处理

调用系统调用时,操作系统是自动会"身份"切换的 ,从用户身份变成内核身份,或者从内核身份变成用户身份

用户态切换为内核态我们称之为陷入内核。每当我们需要陷入内核的时,本质上是因为我们需要执行操作系统的代码,比如系统调用函数是由操作系统实现的,我们要进行系统调用就必须先由用户态切换为内核态

内核空间与用户空间

每一个进程都有自己的进程地址空间,该进程地址空间由内核空间和用户空间组成:

用户所写的代码和数据位于用户空间,通过用户级页表与物理内存之间建立映射关系。
内核空间存储的实际上是操作系统代码和数据,通过内核级页表与物理内存之间建立映射关系

在这里插入图片描述

CR3 寄存器存储了页表的起始物理地址,这个地址指向了页全局目录的起始位置

用户页表有几份?
有几个进程,就有几份用户级页表 , 进程具有独立性

内核页表有几份?
1份

内核级页表是一个全局的页表,它用来维护操作系统的代码与进程之间的关系。因此,在每个进程的进程地址空间中,用户空间是属于当前进程的,每个进程看到的代码和数据是完全不同的,但内核空间所存放的都是操作系统的代码和数据,所有进程看到的都是一样的内容

总结:

  • 每一个进程看到的3到4GB的东西都是一样的
  • 整个系统中,进程再怎么切换,3到4GB的空间的内容是不变的

进程视角:我们调用系统中的方法,就是在我自己的地址空间中进行执行的。

操作系统视角:任何一个时刻,都有有进程执行。我们想执行操作系统的代码,就可以随时执行
在这里插入图片描述

操作系统的本质:基于时钟中断的一个死循环

计算机硬件中,有一个时钟芯片,每个很短的时间,向计算机发送时钟中断

如何理解进程切换?
1、在当前进程的进程地址空间中的内核空间,找到操作系统的代码和数据。
2、执行操作系统的代码,将当前进程的代码和数据剥离下来,并换上另一个进程的代码和数据。
当你访问用户空间时你必须处于用户态,当你访问内核空间时你必须处于内核态

内核如何实现信号的捕捉

当我们在执行主控制流程的时候,可能因为某些情况而陷入内核,当内核处理完毕准备返回用户态时,就需要进行信号pending的检查。(此时仍处于内核态,有权力查看当前进程的pending位图)

在查看pending位图时,如果发现有未决信号,并且该信号没有被阻塞,那么此时就需要该信号进行处理。

如果待处理信号的处理动作是默认或者忽略,则执行该信号的处理动作后清除对应的pending标志位,如果没有新的信号要递达,就直接返回用户态,从主控制流程中上次被中断的地方继续向下执行即可

在这里插入图片描述
但如果待处理信号是自定义捕捉的,即该信号的处理动作是由用户提供的,那么处理该信号时就需要先返回用户态执行对应的自定义处理动作,执行完后再通过特殊的系统调用sigreturn再次陷入内核并清除对应的pending标志位,如果没有新的信号要递达,就直接返回用户态,继续执行主控制流程的代码。
在这里插入图片描述
sighandler和main函数使用不同的堆栈空间,它们之间不存在调用和被调用的关系,是两个独立的控制流程

相关文章:

信号【Linux】

文章目录 信号处理方式&#xff08;信号递达&#xff09;前后台进程 终端按键产生信号kill系统调用接口向进程发信号阻塞信号sigset_tsigprocmasksigpending内核态与用户态&#xff1a;内核空间与用户空间内核如何实现信号的捕捉 1、信号就算没有产生&#xff0c;进程也必须识别…...

Kafka Producer之ACKS应答机制

文章目录 1. 应答机制2. 等级03. 等级14. 等级all5. 设置等级6. ISR 1. 应答机制 异步发送的效率高&#xff0c;但是不安全&#xff0c;同步发送安全&#xff0c;但是效率低。 无论哪一种&#xff0c;有一个关键的步骤叫做回调&#xff0c;也就是ACKS应答机制。 其中ACKS也分…...

【深入理解SpringCloud微服务】深入理解Eureka核心原理

深入理解Eureka核心原理 Eureka整体设计Eureka服务端启动Eureka三级缓存Eureka客户端启动 Eureka整体设计 Eureka是一个经典的注册中心&#xff0c;通过http接收客户端的服务发现和服务注册请求&#xff0c;使用内存注册表保存客户端注册上来的实例信息。 Eureka服务端接收的…...

算法——滑动窗口(day7)

904.水果成篮 904. 水果成篮 - 力扣&#xff08;LeetCode&#xff09; 题目解析&#xff1a; 根据题意我们可以看出给了我们两个篮子说明我们在开始采摘到结束的过程中只能有两种水果的种类&#xff0c;又要求让我们返回收集水果的最大数目&#xff0c;这不难让我们联想到题目…...

Django学习第一天(如何创建和运行app)

前置知识&#xff1a; URL组成部分详解&#xff1a; 一个url由以下几部分组成&#xff1a; scheme&#xff1a;//host:port/path/?query-stringxxx#anchor scheme:代表的是访问的协议&#xff0c;一般为http或者ftp等 host&#xff1a;主机名&#xff0c;域名&#xff0c;…...

VScode连接虚拟机运行Python文件的方法

声明&#xff1a;本文使用Linux发行版本为rocky_9.4 目录 1. 在rocky_9.4最小安装的系统中&#xff0c;默认是没有tar工具的&#xff0c;因此&#xff0c;要先下载tar工具 2. 在安装好的vscode中下载ssh远程插件工具 3. 然后连接虚拟机 4. 查看python是否已经安装 5. 下载…...

通义千问AI模型对接飞书机器人-模型配置(2-1)

一 背景 根据业务或者使用场景搭建自定义的智能ai模型机器人&#xff0c;可以较少我们人工回答的沟通成本&#xff0c;而且可以更加便捷的了解业务需求给出大家设定的业务范围的回答&#xff0c;目前基于阿里云的通义千问模型研究。 二 模型研究 参考阿里云帮助文档&#xf…...

[k8s源码]6.reflector

Reflector 和 Informer 是 Kubernetes 客户端库中两个密切相关但职责不同的组件。Reflector 是一个较低级别的组件&#xff0c;主要负责与 Kubernetes API 服务器进行交互&#xff0c;执行资源的初始列表操作和持续的监视操作&#xff0c;将获取到的数据放入队列中。而 Informe…...

前台文本直接取数据库值doFieldSQL插入SQL

实现功能&#xff1a;根据选择的车间主任带出角色。 实现步骤&#xff1a;OA的“字段联动”功能下拉选项带不出表“hrmrolemembers”&#xff0c;所以采用此方法。 doFieldSQL("select roleid from HrmResource as a inner join hrmrolemembers as b on a.id b.resource…...

【06】LLaMA-Factory微调大模型——微调模型评估

上文【05】LLaMA-Factory微调大模型——初尝微调模型&#xff0c;对LLama-3与Qwen-2进行了指令微调&#xff0c;本文则介绍如何对微调后的模型进行评估分析。 一、部署微调后的LLama-3模型 激活虚拟环境&#xff0c;打开LLaMA-Factory的webui页面 conda activate GLM cd LLa…...

数学建模学习(1)遗传算法

一、简介 遗传算法&#xff08;Genetic Algorithm, GA&#xff09;是一种用于解决优化和搜索问题的进化算法。它基于自然选择和遗传学原理&#xff0c;通过模拟生物进化过程来寻找最优解。 以下是遗传算法的主要步骤和概念&#xff1a; 初始化种群&#xff08;Initialization&a…...

NumPy冷知识66个

NumPy冷知识66个 多维切片: NumPy支持多维切片&#xff0c;可以通过指定多个索引来提取多维数组的子集。 复杂数支持: NumPy可以处理复数&#xff0c;提供了复数的基本运算和函数。 比特运算: NumPy支持比特运算&#xff0c;如与、或、异或等。 数据存储格式: NumPy可以将数…...

Wi-SUN无线通信技术 — 大规模分散式物联网应用首选

引言 在数字化浪潮的推动下&#xff0c;物联网&#xff08;IoT&#xff09;正逐渐渗透到我们生活的方方面面。Wi-SUN技术以其卓越的性能和广泛的应用前景&#xff0c;成为了大规模分散式物联网应用的首选。本文将深入探讨Wi-SUN技术的市场现状、核心优势、实际应用中的案例以及…...

在 Ubuntu Server 22.04 上安装 Docker 的详细步骤

在 Ubuntu Server 22.04 上安装 Docker 的详细步骤 本文档详细记录了在 Ubuntu Server 22.04 上安装 Docker 的完整过程&#xff0c;包括解决过程中遇到的问题。希望能对读者有所帮助。 安装过程&#xff0c;重点需要看官方文档。https://docs.docker.com/engine/install/ubu…...

前端使用 Konva 实现可视化设计器(18)- 素材嵌套 - 加载阶段

本章主要实现素材的嵌套&#xff08;加载阶段&#xff09;这意味着可以拖入画布的对象&#xff0c;不只是图片素材&#xff0c;还可以是嵌套的图片和图形。 请大家动动小手&#xff0c;给我一个免费的 Star 吧~ 大家如果发现了 Bug&#xff0c;欢迎来提 Issue 哟~ github源码 g…...

vue3 -layui项目-左侧导航菜单栏

1.创建目录结构 进入cmd,先cd到项目目录&#xff08;项目vue3-project&#xff09; cd vue3-project mkdir -p src\\views\\home\\components\\menubar 2.创建组件文件 3.编辑menu-item-content.vue <template><template v-if"item.icon"><lay-ic…...

Spring AOP(1)

目录 一、AOP 概述 什么是Spring AOP&#xff1f; 二、Spring AOP 快速入门 1、引入AOP依赖 2、编写AOP程序 三、Spring AOP 详解 1、Spring AOP的核心概念 &#xff08;1&#xff09;切点&#xff08;Pointcut&#xff09; &#xff08;2&#xff09;连接点&#xff…...

第1关 -- Linux 基础知识

闯关任务 完成SSH连接与端口映射并运行hello_world.py ​​​​ ssh -p 37367 rootssh.intern-ai.org.cn -CNg -L 7860:127.0.0.1:7860 -o StrictHostKeyCheckingno可选任务 1 将Linux基础命令在开发机上完成一遍 可选任务 2 使用 VSCODE 远程连接开发机并创建一个conda环境 …...

tensorflow keras Model.fit returning: ValueError: Unrecognized data type

题意&#xff1a;TensorFlow Keras 的 Model.fit 方法返回了一个 ValueError&#xff0c;提示数据类型无法识别 问题背景&#xff1a; Im trying to train a keras model with 2 inputs: an image part thats a tf.data.Dataset and a nor mal part represented by a pd.DataF…...

虚拟机固定配置IP

在Hyper-V中&#xff0c;vEthernet (Default Switch) 是Hyper-V自带的默认虚拟交换机&#xff0c;它允许虚拟机直接连接到宿主机网络或外部网络。这个虚拟交换机可以通过Hyper-V管理器或PowerShell等工具进行管理和配置。以下是具体的操作步骤&#xff1a; 一、通过Hyper-V管理…...

【Pytorch实用教程】pytorch中random_split用法的详细介绍

在 PyTorch 中,torch.utils.data.random_split 是一个非常有用的函数,用于将数据集随机分割成多个子集。这在机器学习和深度学习中非常常见,特别是当你需要将数据集分割成训练集和测试集或验证集时。这里是 random_split 的详细用法介绍: 功能 random_split 用于随机地将…...

第二讲:NJ网络配置

Ethernet/IP网络拓扑结构 一. NJ EtherNet/IP 1、网络端口位置 NJ的CPU上面有两个RJ45的网络接口,其中一个是EtherNet/IP网络端口(另一个是EtherCAT的网络端口) 2、网络作用 如图所示,EtherNet/IP网络既可以做控制器与控制器之间的通信,也可以实现与上位机系统的对接通…...

pytorch中常见的模型3种组织方式 nn.Sequential(OrderedDict)

在nn.Sequential中嵌套OrderedDict组织网络,以对层进行命名 import torch import torch.nn as nn from collections import OrderedDictclass OrderedDictCNN(nn.Module):def __init__(self):super(OrderedDictCNN, self).__init__()# 使用 OrderedDict 定义网络层self.model …...

达梦数据库DM8-索引篇

目录 一、前景二、名词三、语法1、命令方式创建索引1.1 创建索引空间1.2.1 创建普通索引并指定索引数据空间1.2.2 另一种没验证&#xff0c;官方写法1.3 复合索引1.4 唯一索引1.5 位图索引1.6 函数索引 2、创建表时候创建索引3、可视化方式创建索引3.1 打开DM管理工具3.2 找到要…...

【中项】系统集成项目管理工程师-第4章 信息系统架构-4.5技术架构

前言&#xff1a;系统集成项目管理工程师专业&#xff0c;现分享一些教材知识点。觉得文章还不错的喜欢点赞收藏的同时帮忙点点关注。 软考同样是国家人社部和工信部组织的国家级考试&#xff0c;全称为“全国计算机与软件专业技术资格&#xff08;水平&#xff09;考试”&…...

随机梯度下降 (Stochastic Gradient Descent, SGD)

SGD 是梯度下降法的一种变体。与批量梯度下降法不同&#xff0c;SGD 在每次迭代中仅使用一个样本&#xff08;或一个小批量样本&#xff09;的梯度来更新参数。它能更快地更新参数&#xff0c;并且可以更容易地跳出局部最优解。 原理 SGD 的基本思想是通过在每次迭代中使用不…...

TDengine 3.3.2.0 发布:新增 UDT 及 Oracle、SQL Server 数据接入

经过数月的开发和完善&#xff0c;TDengine 3.3.2.0 版本终于问世了。这一版本中既有针对开源社区的功能优化&#xff0c;也有从企业级用户需求出发做出的功能调整。在开源版本中&#xff0c;我们增强了系统的灵活性和兼容性&#xff1b;而在企业级版本中&#xff0c;新增了关键…...

Ubuntu 24.04 LTS 无法打开Chrome浏览器

解决办法&#xff1a; 删除本地配置文件&#xff0c;再次点击Chrome图标&#xff0c;即可打开。 rm ~/.config/google-chrome/ -rf ref: Google chrome not opening in Ubuntu 22.04 LTS - Ask Ubuntu...

linux中RocketMQ安装(单机版)及springboot中的使用

文章目录 一、安装1.1、下载RocketMQ1.2、将下载包上传到linux中&#xff0c;然后解压1.3、修改runserver.sh的jvm参数大小&#xff08;根据自己服务器配置来修改&#xff09;1.4、启动mqnamesrv &#xff08;类似于注册中心&#xff09;1.5、修改runbroker.sh的jvm参数大小&am…...

亚信安全终端一体化解决方案入选应用创新典型案例

近日&#xff0c;由工业和信息化部信息中心主办的2024信息技术应用创新发展大会暨解决方案应用推广大会成功落幕&#xff0c;会上集中发布了一系列技术水平先进、应用效果突出、产业带动性强的信息技术创新工作成果。其中&#xff0c;亚信安全“终端一体化安全运营解决方案”在…...

Django视图与URLs路由详解

在Django Web框架中&#xff0c;视图&#xff08;Views&#xff09;和URLs路由&#xff08;URL routing&#xff09;是Web应用开发的核心概念。它们共同负责将用户的请求映射到相应的Python函数&#xff0c;并返回适当的响应。本篇博客将深入探讨Django的视图和URLs路由系统&am…...

怎么关闭 Windows 安全中心,手动关闭 Windows Defender 教程

Windows 安全中心&#xff08;也称为 Windows Defender Security Center&#xff09;是微软 Windows 操作系统内置的安全管理工具&#xff0c;用于监控和控制病毒防护、防火墙、应用和浏览器保护等安全功能。然而&#xff0c;在某些情况下&#xff0c;用户可能需要关闭 Windows…...

洛谷看不了别人主页怎么办

首先&#xff0c;我们先点进去 可以看到&#xff0c;看不了一点 那我们看向上方&#xff0c;就可以发现&#xff0c;我们那有个URL&#xff0c;选中 把光标插到n和/中间 把.cn删了&#xff0c;变成国际服 我们就可以看了 但是国际服还没搭建完&#xff0c;跳转的时候可能503&a…...

邮件安全篇:企业电子邮件安全涉及哪些方面?

1. 邮件安全概述 企业邮件安全涉及多个方面&#xff0c;旨在保护电子邮件通信的机密性、完整性和可用性&#xff0c;防止数据泄露、欺诈、滥用及其他安全威胁。本文从身份验证与防伪、数据加密、反垃圾邮件和反恶意软件防护、邮件内容过滤与审计、访问控制与权限管理、邮件存储…...

软件测试09 自动化测试技术(Selenium)

重点/难点 重点&#xff1a;理解自动化测试的原理及其流程难点&#xff1a;Selinum自动化测试工具的使用 目录 系统测试 什么是系统测试什么是功能测试什么是性能测试常见的性能指标有哪些 自动化测试概述 测试面临的问题 测试用例数量增多&#xff0c;工作量增大&#xff…...

记录解决springboot项目上传图片到本地,在html里不能回显的问题

项目场景&#xff1a; 项目场景&#xff1a;在我的博客系统里&#xff1a;有个相册模块&#xff1a;需要把图片上传到项目里&#xff0c;在html页面上显示 解决方案 1.建一个文件夹 例如在windows系统下。可以在项目根目录下建个photos文件夹&#xff0c;把上传的图片文件…...

C++ 中 const 关键字

C 中 const 关键字 2009-02-19 2024-07-23 补充C11后的做法 在 C 中&#xff0c;const 是一个关键字&#xff08;也称为保留字&#xff09;&#xff0c;它用于指定变量或对象的值在初始化后不能被修改。关键字是编程语言中具有特殊含义的词汇&#xff0c;编译器会识别这些词并…...

客梯自动监测识别摄像机

当今社会&#xff0c;随着城市建设的快速发展&#xff0c;客梯作为现代化建筑不可或缺的一部分&#xff0c;其安全性与效率显得尤为重要。为了提升客梯的安全管理水平&#xff0c;智能监测技术应运而生&#xff0c;尤其是客梯自动监测识别摄像机系统的应用&#xff0c;为乘客和…...

为什么那么多人学习AI绘画?工资香啊!

在当今这个科技日新月异的时代&#xff0c;AI绘画作为数字艺术与人工智能融合的璀璨成果&#xff0c;正吸引着无数人投身其中&#xff0c;而“工资香啊&#xff01;”无疑是这一热潮背后不可忽视的驱动力之一。 AI绘画的高薪待遇是吸引众多学习者的关键因素。随着市场对AI艺术…...

国产JS库(js-tool-big-box)7月度总结

js-tool-big-box开发已经有3个月了&#xff0c;团队内的小伙伴进行了热烈的讨论&#xff0c;持续做了功能迭代。小伙伴们也做了艰苦卓绝的文档分享&#xff0c;有纯功能分享类的&#xff0c;有带有小故事的&#xff0c;有朋友们利用自己独自网站分发分享的。7月份快要结束了&am…...

c++ 高精度加法(只支持正整数)

再给大家带来一篇高精度&#xff0c;不过这次是高精度加法&#xff01;话不多说&#xff0c;开整&#xff01; 声明 与之前那篇文章一样&#xff0c;如果看起来费劲可以结合总代码来看 定义 由于加法进位最多进1位&#xff0c;所以我们的结果ans[]的长度定义为两个加数中最…...

python键盘操作工具:ctypes、pyautogui

这里模拟 Win Ctrl L 组合键 1、ctypes ctypes库&#xff0c;它允许我们直接调用Windows API来模拟键盘输入。 import ctypes import time# 定义所需的常量和结构 LONG ctypes.c_long DWORD ctypes.c_ulong ULONG_PTR ctypes.POINTER(DWORD) WORD ctypes.c_ushortclass…...

计算机网络发展历史

定义和基本概念 计算机网络是由多个计算设备通过通信线路连接起来的集合&#xff0c;这些设备能够互相交换数据、消息和资源。计算机网络的核心功能是实现数据的远程传输和资源共享&#xff0c;它使得地理位置的限制被大大减弱&#xff0c;极大地促进了信息的自由流动和人类社…...

记录安装android studio踩的坑 win7系统

最近在一台新电脑上安装android studio,报了很多错误&#xff0c;也是费了大劲才解决&#xff0c;发出来大家一起避免一些问题&#xff0c;找到解决方法。 安装时一定要先安装jdk&#xff0c;cmd命令行用java -version查当前的版本&#xff0c;没有的话&#xff0c;先安装jdk,g…...

Python图形编程-PyGame快速入门

PyGame快速入门 文章目录 PyGame快速入门1、什么是PyGame2、安装PyGame3、创建PyGame窗口4、处理事件5、绘制对象6、移动对象7、加载和显示图像8、播放声音9、处理用户输入10、碰撞检测11、动画精灵12、管理游戏状态13、Pygame 中的典型主游戏循环1、什么是PyGame Pygame 是一…...

邦芒宝典:8种方法调整职场心态

在职场中拼斗当然要有好的心态&#xff0c;您知道职场心态如何调整吗&#xff1f; ​ ​方法1&#xff1a;自我调整 ​“思想可以使天堂变成地狱&#xff0c;也可以使地狱变成天堂。”你不能样样顺利&#xff0c;但可以事事尽心;你不能左右天气&#xff0c;但可以改变心情;你…...

华为OD2024D卷机试题汇总,含D量50%+,按算法分类刷题,事半功倍

目录 专栏导读华为OD机试算法题太多了&#xff0c;知识点繁杂&#xff0c;如何刷题更有效率呢&#xff1f; 一、逻辑分析二、数据结构1、线性表① 数组② 双指针 2、map与list3、队列4、链表5、栈6、滑动窗口7、二叉树8、并查集9、矩阵 三、算法1、基础算法① 贪心思维② 二分查…...

Unity UGUI 之 Graphic Raycaster

本文仅作学习笔记与交流&#xff0c;不作任何商业用途 本文包括但不限于unity官方手册&#xff0c;唐老狮&#xff0c;麦扣教程知识&#xff0c;引用会标记&#xff0c;如有不足还请斧正 首先手册连接如下&#xff1a; Unity - Manual: Graphic Raycaster 笔记来源于&#xff…...

类和对象——相关的零碎知识

前提提示&#xff1a; 其实C中的类和对象&#xff0c;最重要的是6个默认函数&#xff0c;如有忘记&#xff0c;请移步到&#xff1a;类和对象。本章是对于一些细节知识的补充和拓展。 1. 隐示类型转换 在运算时&#xff0c;运算符左右两边的操作数的类型不同&#xff0c;编译器…...

【hadoop大数据集群 1】

hadoop大数据集群 1 文章目录 hadoop大数据集群 1一、环境配置1.安装虚拟机2.换源3.安装工具4.安装JDK5.安装Hadoop 一、环境配置 折腾了一下午/(ㄒoㄒ)/~~ 1.安装虚拟机 参考视频&#xff1a;https://www.bilibili.com/video/BV18y4y1G7JA?p17&vd_sourcee15e83ac6b22a…...