探索进程控制第一弹(进程终止、进程等待)

news2025/6/28 5:18:14

文章目录

  • 进程创建
    • 初识fork函数
    • fork函数返回值
    • fork常规用法
    • fork调用失败的原因
  • 写时拷贝
  • 进程终止
    • 进程终止是在做什么?
    • 进程终止的情况
      • 代码跑完,结果正确/不正确
      • 代码异常终止
    • 如何终止
  • 进程等待
    • 概述
    • 进程等待方法
      • wait方法
      • waitpid

在这里插入图片描述

进程创建

初识fork函数

在linux中fork函数时非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。

#include <unistd.h>
pid_t fork(void);

返回值:自进程中返回0,父进程返回子进程id,出错返回-1。

进程=内核相关管理数据结构(task_struct、mm_struct、页表)+代码和数据

对于每一个进程都需要:

  • 分配新的内存块和内核数据结构给子进程
  • 将父进程部分数据结构内容拷贝至子进程
  • 添加子进程到系统进程列表当中
  • fork返回,开始调度器调度

在这里插入图片描述

如何理解进程具有独立性??子进程中也有相关管理数据结构也有自己的代码和数据,代码和数据虽然和父进程共享,但是和父进程相互不影响,数据的部分是以写时拷贝时私有,不写时拷贝相当于共享。

当一个进程调用fork之后,就有两个二进制代码相同的进程。而且它们都运行到相同的地方。但每个进程都将可以开始它们自己的旅程。

fork函数返回值

  • 子进程返回0
  • 父进程返回的是子进程的pid

如何做到有两个返回值?
探索父进程和子进程 文章中有详细解释。

为什么给父进程返回的是子进程的pid,给子进程返回0?
父进程必须知道子进程的pid,方便后续对子进程进行标识,进而进行管理;子进程需要通过返回0,来看是否创建成功。

fork常规用法

  • 一个父进程希望复制自己,使父子进程同时执行不同的代码段。例如,父进程等待客户端请求,生成子进程来处理请求。
  • 一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数

fork调用失败的原因

  • 系统中有太多的进程
  • 实际用户的进程数超过了限制

写时拷贝

通常,父子代码共享,父子再不写入时,数据也是共享的,当任意一方试图写入,便以写时拷贝的方式各自一份副本。

在这里插入图片描述


进程终止

进程终止是在做什么?

在进程创建的时候,是先有内核数据结构,再有的代码和数据。
终止一个进程的本质是在释放曾经的代码和数据所占据的空间,释放内核数据结构。
在释放内核数据结构时,PCB会延迟释放。

进程终止的情况

代码跑完,结果正确/不正确

在这里插入图片描述

main函数的返回值是100,通过echo $?查询。在系统中有一个变量叫做?,查看这个变量使用$?,访问变量内容都可以使用echoecho是内建命令,打印的都是bash内部的变量数据。
$?表示父进程bash获取到的最近一个子进程退出的退出码。退出码为0表示成功,非0表示失败,不同的非0值一方面表示失败,另一方面表示失败原因,每个数字的错误描述都是由操作系统规定,对应的错误描述都是一个字符串。因此平时在写代码时,main函数内部都是return 0,我们在编写C/C++代码都是默认成功的。

#include<stdio.h>    
#include<unistd.h>    
#include<string.h>    
    
int main()    
{    
  for(int errcode=0;errcode<=255;errcode++)    
  {    
    printf("%d:%s\n",errcode,strerror(errcode));                                                                                         
  }    
  printf("I am process,pid:%d,ppid:%d\n",getpid(),getppid());    
  sleep(2);    
  return 100;    
}    

运行结果:

[gwj@iZf8zhv7mi2thjdxsptkb8Z lesson16]$ make
gcc -o myprocess myprocess.c -std=c99
[gwj@iZf8zhv7mi2thjdxsptkb8Z lesson16]$ ./myprocess 
0:Success
1:Operation not permitted
2:No such file or directory
3:No such process
4:Interrupted system call
5:Input/output error
6:No such device or address
7:Argument list too long
8:Exec format error
9:Bad file descriptor
10:No child processes
11:Resource temporarily unavailable
12:Cannot allocate memory
13:Permission denied
14:Bad address
15:Block device required
16:Device or resource busy
17:File exists
18:Invalid cross-device link
19:No such device
20:Not a directory
21:Is a directory
22:Invalid argument
23:Too many open files in system
24:Too many open files
25:Inappropriate ioctl for device
26:Text file busy
27:File too large
28:No space left on device
29:Illegal seek
30:Read-only file system
31:Too many links
32:Broken pipe
33:Numerical argument out of domain
34:Numerical result out of range
35:Resource deadlock avoided
36:File name too long
37:No locks available
38:Function not implemented
39:Directory not empty
40:Too many levels of symbolic links
41:Unknown error 41
42:No message of desired type
43:Identifier removed
44:Channel number out of range
45:Level 2 not synchronized
46:Level 3 halted
47:Level 3 reset
48:Link number out of range
49:Protocol driver not attached
50:No CSI structure available
51:Level 2 halted
52:Invalid exchange
53:Invalid request descriptor
54:Exchange full
55:No anode
56:Invalid request code
57:Invalid slot
58:Unknown error 58
59:Bad font file format
60:Device not a stream
61:No data available
62:Timer expired
63:Out of streams resources
64:Machine is not on the network
65:Package not installed
66:Object is remote
67:Link has been severed
68:Advertise error
69:Srmount error
70:Communication error on send
71:Protocol error
72:Multihop attempted
73:RFS specific error
74:Bad message
75:Value too large for defined data type
76:Name not unique on network
77:File descriptor in bad state
78:Remote address changed
79:Can not access a needed shared library
80:Accessing a corrupted shared library
81:.lib section in a.out corrupted
82:Attempting to link in too many shared libraries
83:Cannot exec a shared library directly
84:Invalid or incomplete multibyte or wide character
85:Interrupted system call should be restarted
86:Streams pipe error
87:Too many users
88:Socket operation on non-socket
89:Destination address required
90:Message too long
91:Protocol wrong type for socket
92:Protocol not available
93:Protocol not supported
94:Socket type not supported
95:Operation not supported
96:Protocol family not supported
97:Address family not supported by protocol
98:Address already in use
99:Cannot assign requested address
100:Network is down
101:Network is unreachable
102:Network dropped connection on reset
103:Software caused connection abort
104:Connection reset by peer
105:No buffer space available
106:Transport endpoint is already connected
107:Transport endpoint is not connected
108:Cannot send after transport endpoint shutdown
109:Too many references: cannot splice
110:Connection timed out
111:Connection refused
112:Host is down
113:No route to host
114:Operation already in progress
115:Operation now in progress
116:Stale file handle
117:Structure needs cleaning
118:Not a XENIX named type file
119:No XENIX semaphores available
120:Is a named type file
121:Remote I/O error
122:Disk quota exceeded
123:No medium found
124:Wrong medium type
125:Operation canceled
126:Required key not available
127:Key has expired
128:Key has been revoked
129:Key was rejected by service
130:Owner died
131:State not recoverable
132:Operation not possible due to RF-kill
133:Memory page has hardware error
134:Unknown error 134
135:Unknown error 135
136:Unknown error 136
137:Unknown error 137
138:Unknown error 138
139:Unknown error 139
140:Unknown error 140
141:Unknown error 141
142:Unknown error 142
143:Unknown error 143
144:Unknown error 144
145:Unknown error 145
146:Unknown error 146
147:Unknown error 147
148:Unknown error 148
149:Unknown error 149
150:Unknown error 150
151:Unknown error 151
152:Unknown error 152
153:Unknown error 153
154:Unknown error 154
155:Unknown error 155
156:Unknown error 156
157:Unknown error 157
158:Unknown error 158
159:Unknown error 159
160:Unknown error 160
161:Unknown error 161
162:Unknown error 162
163:Unknown error 163
164:Unknown error 164
165:Unknown error 165
166:Unknown error 166
167:Unknown error 167
168:Unknown error 168
169:Unknown error 169
170:Unknown error 170
171:Unknown error 171
172:Unknown error 172
173:Unknown error 173
174:Unknown error 174
175:Unknown error 175
176:Unknown error 176
177:Unknown error 177
178:Unknown error 178
179:Unknown error 179
180:Unknown error 180
181:Unknown error 181
182:Unknown error 182
183:Unknown error 183
184:Unknown error 184
185:Unknown error 185
186:Unknown error 186
187:Unknown error 187
188:Unknown error 188
189:Unknown error 189
190:Unknown error 190
191:Unknown error 191
192:Unknown error 192
193:Unknown error 193
194:Unknown error 194
195:Unknown error 195
196:Unknown error 196
197:Unknown error 197
198:Unknown error 198
199:Unknown error 199
200:Unknown error 200
201:Unknown error 201
202:Unknown error 202
203:Unknown error 203
204:Unknown error 204
205:Unknown error 205
206:Unknown error 206
207:Unknown error 207
208:Unknown error 208
209:Unknown error 209
210:Unknown error 210
211:Unknown error 211
212:Unknown error 212
213:Unknown error 213
214:Unknown error 214
215:Unknown error 215
216:Unknown error 216
217:Unknown error 217
218:Unknown error 218
219:Unknown error 219
220:Unknown error 220
221:Unknown error 221
222:Unknown error 222
223:Unknown error 223
224:Unknown error 224
225:Unknown error 225
226:Unknown error 226
227:Unknown error 227
228:Unknown error 228
229:Unknown error 229
230:Unknown error 230
231:Unknown error 231
232:Unknown error 232
233:Unknown error 233
234:Unknown error 234
235:Unknown error 235
236:Unknown error 236
237:Unknown error 237
238:Unknown error 238
239:Unknown error 239
240:Unknown error 240
241:Unknown error 241
242:Unknown error 242
243:Unknown error 243
244:Unknown error 244
245:Unknown error 245
246:Unknown error 246
247:Unknown error 247
248:Unknown error 248
249:Unknown error 249
250:Unknown error 250
251:Unknown error 251
252:Unknown error 252
253:Unknown error 253
254:Unknown error 254
255:Unknown error 255
I am process,pid:32312,ppid:31371

对应的错误码都表示一种错误。

父进程为什么知道子进程退出码?父进程要知道子进程的退出情况(失败了还是成功了,失败的原因是什么),bash会反馈给用户。

举个例子:

在这里插入图片描述

进程的退出码存在的意义是告诉关心方(父进程),我把任务执行的怎么样了。既然把子进程创建出来,就要让父进程得到信息。

在这里插入图片描述

不是说echo $?保存的是最近一个子进程退出的退出码吗?那上图怎么解释?方框中第一个echo $?执行的命令是查看process的退出码,第二个echo $?查看的是第一个echo $?的退出码,虽然echo是一个内建命令,但是也是当做进程来看待。

进程的退出码可以使用系统官方的定义,你也可以自定义一个退出码。

代码异常终止

代码执行时,出现了异常,提前退出,一旦进程出现异常,退出码有没有意义了

vs编写程序运行时,程序崩溃了,本质是操作系统发现你的程序做了不该做的事情,操作系统杀掉了你的进程。

为什么进程会出现异常?
本质上是因为进程收到了操作系统发出的信号。

段错误,操作系统提前终止进程。

在这里插入图片描述
尽管书写的代码进程没有错误,但是接收到了信号,就会有段错误。

进程退出时,我们可以看进程退出信号是多少来判断进程为什么异常。

进程退出的三种情况:
代码运行完毕,结果正确
代码运行完毕,结果不正确
代码异常终止

因此,衡量一个进程退出,我们只需要看两个数字:退出码、退出信号

如何终止

  1. main函数中直接return,表示进程终止(非main函数,return函数结束)
  2. 代码调用exit(),注意:在代码任意位置调用都表示进程终止。
#include<stdio.h>    
#include<unistd.h>    
#include<string.h>    
#include<stdlib.h>                                                 
int main()    
{    
  while(1)    
  {    
    printf("I am process,pid:%d,ppid:%d\n",getpid(),getppid());
    sleep(2);    
    exit(123);    
  }    
  return 100;    
}  

在这里插入图片描述

#include <unistd.h>
void exit(int status);

exit最后也会调用exit, 但在调用exit之前,还做了其他工作:

  • 执行用户通过 atexit或on_exit定义的清理函数。
  • 关闭所有打开的流,所有的缓存数据均被写入
  • 调用_exit
  1. 调用_exit()函数
#include <unistd.h>
void _exit(int status);

参数:status 定义了进程的终止状态,父进程通过wait来获取该值
说明:虽然status是int,但是仅有低8位可以被父进程所用。所以_exit(-1)时,在终端执行$?发现返回值是255。

#include<stdio.h>    
#include<unistd.h>    
#include<string.h>    
#include<stdlib.h>                                                 
int main()    
{    
  while(1)    
  {    
    printf("I am process,pid:%d,ppid:%d\n",getpid(),getppid());
    sleep(2);    
    _exit(-1);    
  }    
  return 100;    
}  

在这里插入图片描述


exit_exit区别:
exit会在程序退出时,冲刷缓冲区,_exit不会。

在这里插入图片描述

进程等待

概述

什么是进程等待?
任何子进程,在退出的情况下,一般必须要被父进程等待。 进程在退出的时候,如果父进程不管不顾,退出进程,处于僵尸状态(Z),存在内存泄漏。


为什么?

  1. 父进程通过等待,解决子进程退出的僵尸问题,回收系统资源(一定要考虑的)
  2. 父进程获取子进程的退出信息,知道子进程退出原因(可选的功能)

进程等待方法

wait方法

#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int*status);

返回值:
成功返回被等待进程pid,失败返回-1。
参数:
输出型参数,获取子进程退出状态,不关心则可以设置成为NULL。

代码势力:

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>

void ChildRun()
{
  int cnt=5;
  while(cnt)
  {
    printf("I am child process,pid:%d,ppid:%d,cnt=%d\n",getpid(),getppid(),cnt);
    sleep(1);
    cnt--;
  }
}

int main()
{
  printf("I am father,pid:%d,ppid:%d\n",getpid(),getppid());
  pid_t id=fork();

  if(id==0)                                                                        
  {
    //child
    ChildRun();
    printf("child process quit...\n");
    exit(0);
  }

  sleep(10);
  //father
  pid_t rid=wait(NULL);
  if(rid>0)
  {
    printf("wait process,rid:%d\n",rid);
  }

  sleep(3);
  printf("father process quit...\n");
  return 0;
}

运行结果:

在这里插入图片描述

在上述代码中,先进入父进程,然后子进程运行五次后子进程退出,然后休眠10秒,处于僵尸状态,紧接着进程等待,然后父进程退出,程序运行结束。由此可以看出,等待会解决进程的僵尸问题。

将上述代码sleep(10)代码注释掉,子进程运行5秒后直接退出,立马执行父进程等待。如果子进程没有退,其实父进程一直在阻塞等待。子进程本身是软件,父进程本质是在等待某种软件就绪。
进程的等待本质是将进程的PCB列入等待队列。那么如何理解父进程阻塞等待子进程?父进程不被调度,在执行wait发现子进程还没有退出,父进程就不要调度,实际上就是将父进程PCB列入等待队列,处于S状态(非运行状态),等到子进程退出,唤醒父进程。

waitpid

#include <sys/types.h>
#include <sys/wait.h>

pid_t wait(int *status);

pid_t waitpid(pid_t pid, int *status, int options);

int  waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);

  • 返回值:

当正常返回的时候waitpid返回收集到的子进程的进程ID;
如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;

  • 参数:

  • [ ]

  • pid:

  1. Pid=-1,等待任一个子进程。与wait等效。
    pid_t rid=waitpid(-1,NULL,0);等待任何一个子进程退出,哪一个进程退了,就对应返回哪一个进程的pid。等同于 pid_t rid=wait(NULL);

  2. Pid>0.等待其进程ID与pid相等的子进程。

  3. pid_t rid=waitpid(id,NULL,0);

  • status:典型输出型参数
  1. WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
  2. WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)

以位图的形式返回
在这里插入图片描述
退出码范围:0~255
信号终止:128个

代码:

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>

void ChildRun()
{
  int cnt=5;
  while(cnt)
  {
    printf("I am child process,pid:%d,ppid:%d,cnt=%d\n",getpid(),getppid(),cnt);
    sleep(1);
    cnt--;
  }
}

int main()
{
  printf("I am father,pid:%d,ppid:%d\n",getpid(),getppid());
  pid_t id=fork();

  if(id==0)                                                                                                                        
  {
    //child
    ChildRun();
    printf("child process quit...\n");
    exit(1);
  }

  sleep(7);
  //father
  //pid_t rid=wait(NULL);
  int status=0;
  pid_t rid=waitpid(id,&status,0);
  if(rid>0)
  {
    printf("wait process,rid:%d\n",rid);
  }

  sleep(3);
  printf("father process quit,status:%d,child quit code:%d,child quit signal:%d\n",status,(status>>8)&0xFF,status & 0x7F);

  return 0;
}

运行结果:

在这里插入图片描述

  • options:
    WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进程的ID。

在这里插入图片描述

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

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

相关文章

C++ 线程库(thread)与锁(mutex)

一.线程库(thread) 1.1 线程类的简单介绍 thread类文档介绍 在C11之前&#xff0c;涉及到多线程问题&#xff0c;都是和平台相关的&#xff0c;比如windows和linux下各有自己的接口&#xff0c;这使得代码的可移植性比较差。C11中最重要的特性就是对线程进行支持了&#xff…

数据结构与算法——字符串暴力匹配

一、字符串的组成 1.数据域&#xff0c;字符串的内容 2.字符串的长度 二、模式匹配-暴力匹配原理 1.两个字符串一个主串一个模式串用两个指针对其进行匹配 2、两个指针所对应的值相同时继续匹配下一个 3、当出现不匹配的情况时&#xff0c;回溯主串的指针到刚开始起点的下一个位…

IP地址定位技术在各领域的作用

IP地址定位是通过确定IP地址的物理位置来定位一个设备的技术&#xff0c;它在现代社会的多个领域中都有着广泛的应用。以下将详细探讨IP地址定位的应用场景&#xff0c;以期对读者有所启发。 首先&#xff0c;在网络安全领域&#xff0c;IP地址定位发挥着至关重要的作用。网络…

业务逻辑漏洞(靶场) fiddler

目录 fiddler简介&#xff1a; 业务逻辑漏洞&#xff1a; fiddler下载 靶场&#xff1a; 实验一 ​编辑实验二&#xff08;ps 更改实验url会变&#xff0c;fiddler没抓到东西看看代理改没改&#xff09; 实验三 实验四 fiddler简介&#xff1a; 一款网络抓包工具&#…

如何丝滑地切换node版本

背景 由于有些比较老的系统&#xff0c;使用的node版本较低&#xff0c;本机装的node版本又比较高&#xff0c;不想降node版本&#xff0c;那么就需要考虑能不能在系统里管理多个node版本呢&#xff1f;由于我使用的操作系统是Mac&#xff0c;下面将主要讲解如何在Mac上快速切…

Tmux 使用笔记

Tmux 是一个终端复用器&#xff08;terminal multiplexer&#xff09;&#xff0c;非常有用&#xff0c;属于常用的开发工具。 本文记录个人使用 Tmux的命令。 1. tmux简介 命令行的典型使用方式是&#xff0c;打开一个终端窗口&#xff0c;连接计算机&#xff0c;在里面输入…

LeetCode-热题100:148. 排序链表

题目描述 给你链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排序后的链表 。 示例 1&#xff1a; 输入&#xff1a; head [4,2,1,3] 输出&#xff1a; [1,2,3,4] 示例 2&#xff1a; 输入&#xff1a; head [-1,5,3,4,0] 输出&#xff1a; [-1,0,3,4,5] 示例…

探索未来产业:新技术、新商业、新趋势

引言 随着科技的迅速发展和全球经济的不断变化&#xff0c;未来产业已经成为全球关注的焦点之一。未来产业的兴起不仅代表着新的商业机遇&#xff0c;更是对传统产业模式的颠覆和重构。在这个充满挑战和机遇的时代&#xff0c;我们不得不认真思考未来产业的重要性和前景。 未…

现在软考考什么科目最好?

适合你的学科才是最适合你的学科。 在软考的同一级别&#xff0c;证书的价值差不多。只能说有些学科比较受欢迎&#xff0c;需求量比较大。 中级的系统集成项目管理工程师是最受欢迎的考试科目&#xff0c;其次是软件设计师和网络工程师。由于市场需求大&#xff0c;报考人数也…

gradio简单搭建——关键词匹配筛选【进一步优化】

gradio简单搭建——关键词匹配筛选[进一步优化] 任务回顾新的想法&#xff1a;无效元素筛选界面搭建数据处理与生成过程交互界面展示 任务回顾 在 apply \text{apply} apply方法的使用一节中&#xff0c;简单提到了任务目标&#xff1a;通过关键词的形式&#xff0c;在文本数据…

DNS 各记录类型说明及规则

各记录类型使用目的 记录类型使用目的A 记录将域名指向一个 IP 地址。CNAME 记录将域名指向另一个域名&#xff0c;再由另一个域名提供 IP 地址。MX 记录设置邮箱&#xff0c;让邮箱能收到邮件。NS 记录将子域名交给其他 DNS 服务商解析。AAAA 记录将域名指向一个 IPv6 地址。…

VMware vSphere虚拟化基础管理平台

VMware简介 VMware介绍 官网&#xff1a;https://www.vmware.com/cn.html VMware公司成立于1998年&#xff0c;2003年存储厂商EMC以6.35亿美元收购了VMware&#xff1b;2015年10月&#xff0c;戴尔宣布以670亿美元收购EMC。VMware公司在2018年全年收入79.2亿美元。 VMware主…

20240326-1-KNN面试题

KNN面试题 1.简述一下KNN算法的原理 KNN算法利用训练数据集对特征向量空间进行划分。KNN算法的核心思想是在一个含未知样本的空间&#xff0c;可以根据样本最近的k个样本的数据类型来确定未知样本的数据类型。 该算法涉及的3个主要因素是&#xff1a;k值选择&#xff0c;距离度…

AOF文件重写

1.2.3.AOF文件重写 因为是记录命令&#xff0c;AOF文件会比RDB文件大的多。而且AOF会记录对同一个key的多次写操作&#xff0c;但只有最后一次写操作才有意义。通过执行bgrewriteaof命令&#xff0c;可以让AOF文件执行重写功能&#xff0c;用最少的命令达到相同效果。 如图&am…

SolidWorks上手直接开整

本科学3D建模的时候&#xff0c;学习过犀牛Rhine&#xff0c;当时就惊叹于入籍紧密集成的可视化编程环境&#xff0c;后来又简单学习过了3DMax、Maya&#xff0c;平时使用的频率不多&#xff0c;所以还是初学者水平&#xff0c;现在课题组需要自研一个原型机&#xff0c;需要工…

图片管理系统:原理、设计与实践

title: 图片管理系统&#xff1a;原理、设计与实践 date: 2024/4/9 20:04:25 updated: 2024/4/9 20:04:25 tags: 图片管理存储组织上传采集处理编辑搜索检索展示分享AI应用 第一章&#xff1a;图片管理系统概述 1.1 图片管理系统简介 图片管理系统是一种用于存储、组织、处理…

Redux和Redux Toolkit

Redux 概念&#xff1a;redux是react最常用的集中状态管理工具&#xff0c;类似于Vue中的Pinia(vuex)&#xff0c;可以独立于框架运行作用&#xff1a;通过集中管理的方式管理应用的状态 Redux快速体验 不和任何框架绑定&#xff0c;不使用任何构建工具&#xff0c;使用纯Re…

kali linux 安装 VirtualBox for Linux Hosts

sudo vim /etc/apt/sources.list deb [archamd64] https://download.virtualbox.org/virtualbox/debian buster contrib添加源文件 sudo apt update sudo apt install linux-headers-$(uname -r) dkms sudo apt install virtualbox virtualbox-ext-pack 扩展包 echo "d…

干货分享|JumpServer三种常见的文件传输方式效果对比

JumpServer开源堡垒机支持对文件的上传和下载&#xff0c;并对传输记录进⾏审计。JumpServer的文件传输功能是用户使用频率较高的功能&#xff0c;常见的文件传输方式包括&#xff1a;rz和sz命令方式、文件管理方式和客户端工具方式。 在使用JumpServer进行文件传输的时候&…

【SpringBoot3】Bean管理

1.Bean扫描 1.1传统Spring 标签&#xff1a;<context:component-scan base-package"com. example "/>注解&#xff1a;ComponentScan(basePackages "com.example") 1.2SpringBoot SpringBoot默认扫描启动类所在的包及其子包 2.Bean注册 如果要注…