【Linux】进程概念
目录
一、基本概念
二、查看进程
三、系统调用获取进程标示符
1、获取自己的PID
2、获取父进程的PID
四、创建进程
1、初识fork
2、使用fork的方式
五、进程状态
1、阻塞
2、挂起
3、R状态
4、S状态
5、D状态
6、T状态
6.1、kill指令
6.2、暂停进程与继续进程
6.3、杀死进程
7、X && Z 状态
一、基本概念
在大多数课本中,对于进程概念的讲解大致是:程序的一个执行实例、正在执行的程序等等。这种说法是不够全面的,现在我来带领大家更加深入细致的了解进程。在正式学习之前,为了大家更好的理解,我先来举一个例子。
如果有一个社会人士,想要成为你们学校的学生,那么他需要满足什么样的条件呢?只需要他本人进入到你们的学校,在学校内活动就可以了吗?这显然是不行的,判断一个人是不是这个学校的学生,依据的是这个人有没有被学校所管理,学校会不会给他排课,给他计学分、发毕业证。
所以同样的,把一个可执行程序变为进程,不仅仅要把该可执行程序加载到内存中,还要让这个可执行程序被操作系统所管理。
我们编写生成的可执行程序本质上是一个普通二进制文件,储存在磁盘之中。当我们使用 ./ 运行该可执行程序时,会先把该文件的代码和数据加载到内存中,做到这一步,就相当于一个社会人士本人进入到了学校之中,但是这样就叫做进程了吗?显然不可能,这些代码和数据还需要被操作系统所管理。那么操作系统如何管理被加载到内存中的数据呢?遵循我们之前文章中提到的六个字原则:先描述,再组织。
每一个进程在加载到内存之时,操作系统会在内核之中创建一个数据结构对象,这个数据结构叫做 PCB(process control block),在Linux操作系统下的PCB是 task_struct 。这些结构体对象提取并填充了对应进程的属性,并且每个结构体对象里都有一个指向其对应代码和数据的指针。这就是先描述的过程。
这样随着多个进程加载到内存中,操作系统内核里也就有了多个描述结构体,这些结构体都叫 PCB,并以特定的数据结构连接起来。这就是再组织的过程。
此后所有对于进程的管理都被转换成了对数据结构PCB的增删查改,这是一个对进程的管理建模的过程。
总结:进程是内核关于进程的相关数据结构与当前进程的代码和数据的结合。很多课本中着重的强调了当前进程的代码和数据的部分,而忽略掉了内核中相关数据结构的部分。
由于 Linux 是使用C语言写的,所以Linux操作系统下的 task_struct 就是结构体。
我们知道文件包括内容和属性,那么在操作系统中,为了管理进程所创建的PCB中的进程属性与磁盘中文件的属性有关联吗?有关联,但是关联不大,有关联的部分包括文件属性中的权限、名称、大小等等,但大部分的属性是没有关联的。
PCB结构体是一种内核数据结构,是由操作系统重起炉灶创建和维护的,里面的进程属性和磁盘文件的属性基本没有关系。它会被装载到RAM(内存)里并且包含着进程的属性信息:
- 标示符: 描述本进程的唯一标示符,用来区别其他进程。
- 状态: 任务状态,退出代码,退出信号等。
- 优先级: 相对于其他进程的优先级。
- 程序计数器: 程序中即将被执行的下一条指令的地址。
- 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
- 上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。
- I/ O状态信息: 包括显示的I/O请求,分配给进程的I/ O设备和被进程使用的文件列表。
- 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
- 其他信息
二、查看进程
我们先编写一个程序:
并把它编译形成一个可执行文件。此时,我们使用 ./ 来运行这个可执行文件就会自动创建一个进程。
查看进程指令:
ps axj
查看当前所有系统中的进程:
如果我们只想看我们自己的进程,则可以使用 grep 来进行过滤:
ps axj | grep [进程名]
此时就可以看到有一个 myprocess 进程在进行,至于下面第二行中的 grep -color=automyprocess字样,则是因为我们在系统之中查找进程时,由于 grep 文本过滤自己也是一个进程,就会导致自己把自己也给过滤出来了,并且显示在下面,如果不想看到这一行,可以通过指令 grep -v grep 来避免显示。
现在我们再启动一次这个可执行程序,并且观察进程:
这时就可以看到两个进程在进行了。我们观察这两个进程:
可以发现其中一个属性 PID 是不同的,这说明同一个可执行程序被启动了两次,所产生的是两个不同的进程。换言之,把一个可执行程序多次加载到内存中,会存在多个进程。
除了使用 ps 命令查看进程之外,还有一种方式可以查看进程,那就是查看 proc 目录。proc 目录是一个内存级的文件系统,只有当操作系统启动的时候,它才会存在,在磁盘上并不存在 proc 目录。我们可以通过该目录查到内存相关的信息:
这一大堆蓝色的都是目录名称,其中蓝色数字就是系统中特定进程的 PID ,我们进入其中一个以新增进程的 PID 命名的目录,就可以看到所启动的进程相关的属性了:
其中有两个属性我们比较熟悉,一个是可执行程序对应的路径,一个是可执行程序的名称。这就是为什么说管理进程所创建的PCB中的进程属性与磁盘中文件的属性有小部分关联,就体现在这里。
现在我们把两个新增进程终止掉:
Ctrl + c
此时,我们再在 proc 目录中查看以进程 PID 命名的目录时,就会提示进程不存在:
所以 proc 目录里的内容是动态变化的。
三、系统调用获取进程标示符
1、获取自己的PID
获取进程自己的PID的系统调用:
getpid
通过 man 指令来查看 getpid :
通过函数说明,我们得知谁调用这个函数,就获取谁的PID。
现在我们通过编写程序来更加直观的感受一下:
运行生成的可执行程序:
就可以直接看到该进程的PID了。现在我们使用 Ctrl+c 终止该进程,然后再重新运行可执行文件生成新的进程,再来观察一下:
可以看到每次重新启动进程,PID都不一样,这是很正常的,因为每一次进程在加载启动的时候,操作系统就创建PID,PID是操作系统来维护的,线性递增。
2、获取父进程的PID
获取父进程的PID的系统调用:
getppid
重新编写代码:
运行生成的可执行程序:
可以看到该进程的PID与PPID,现在我们使用 Ctrl+c 来终止该进程,并重新运行可执行程序生成新的进程:
可以发现进程的PID在不断的变化,而PPID却没有变化,那么PPID是谁呢?
我们通过 ps 指令查看该进程:
发现这个父进程其实是 bash ,即命令行解释器。
结论:
- bash命令行解释器,本质上也是一个进程
- 命令行启动的所有的程序,最终都会变成进程,而该进程对应的父进程都是bash
那么 bash 为什么要创建子进程来执行程序呢?这是为了防止我们执行的程序发生错误,如果 bash 自己来执行程序,如果程序挂了,那么 bash 也就挂了,这是相当危险的事情。
四、创建进程
1、初识fork
在以前,我们熟悉的创建进程的方式有两种,第一种是在Windows系统下,我们双击一个 .exe 文件,就创建了一个进程,还有一种是在Linux系统下,我们通过在命令行输入 ./ 来将程序变成进程去运行。
现在我们再来学习一种创建进程的方式,通过系统调用:
fork
我们通过实际操作来学习如何使用 fork :
编辑程序:
运行生成的可执行程序:
发现打印了一行A,却打印了两行B,这是什么原因呢?
我们修改一下程序,输出打印B这一行函数的进程与父进程:
运行可执行程序:
发现这两行打印的进程不同,这可以说明这两行是两个不同的进程,之后又发现第二行打印的父进程,刚好是第一行打印的进程,这说明这两个进程是父子关系。此时我们就完成了创建子进程的操作。那我们如何控制父进程与子进程呢?
通过查找 man 手册,我们来研究一下 fork 函数:
手册说明:fork 的返回值类型是 pid_t(即有符号整数)。进程创建成功,子进程的PID会返回给父进程,0 会返回给子进程。进程创建失败,-1 会被返回给父进程。
我们依旧通过实际操作来理解:
运行可执行程序:
这时观察到了一个奇怪的现象:打印两次 ret 的值不同,为什么一个函数会有两个返回值呢?这两个 ret 的地址相同,说明他们是同一个变量,但是为什么打印出了两个不一样的值呢?
首先我们需要知道 fork 做了什么,进程 = 内核数据结构 + 进程的代码和数据,当我们创建子进程的时候,并不是把代码和数据又拷贝了一份,而是在内核中再创建一个子进程PCB,子进程PCB的大部分属性会以父进程PCB为模板,并把属性信息拷贝进来。
父进程的PCB指向自己的代码和数据,子进程PCB也指向同样的代码和数据。所以 fork 就相当于在内核中创建独立的PCB结构,并让子进程与父进程共享一份代码和数据。
进程在运行的时候是有独立性的,任何一个进程出现故障不会影响其他进程,父子进程运行的时候也是一样的。
代码:代码是只读的,所以进程无法修改代码,也就无法相互影响
数据:当有一个执行流尝试修改数据的时候,OS会自动给当前进程触发一个机制:写时拷贝,简单来说就是在写入的时候,OS会把该数据重新拷贝一份,此时写入、修改就在这个备份上执行,而不会修改原始数据。从而在数据上也能保持无法相互影响。
有了以上的知识储备,我们再来研究 fork 如何拥有两个返回值。我们知道,当一个函数准备执行 return 语句的时候,该函数的主体功能就已经完成了,return 语句不影响函数的功能,仅仅起到返回结果的作用。因此, fork 系统调用函数在执行 return 语句之前,子进程就已经创建完成并已经在进行中了,所以当执行 return 语句返回结果的时候,就要给父进程与子进程各自返回一份结果,即执行了两次。最终返回结果被赋值给变量 ret 的时候,OS自动触发了写时拷贝,分别把结果存入两者的备份空间中。至于为什么打印出来的 ret 的地址是相同的,这与虚拟地址有关,下面会讲。
总结:
- fork有两个返回值
- 父子进程代码共享,数据各自开辟空间,私有一份(采用写时拷贝)
2、使用fork的方式
一般情况下,我们使用 fork 创建子进程之后通常要用 if 进行分流:
编译运行:
fork之后,执行流会变成两个执行流,谁先运行由调度器决定。父子进程通过 if 分流分别执行不同的代码块。
五、进程状态
进程在CPU上运行的时候,并不是一直在运行的,而是一个进程先在CPU上运行一会,再切换另一个进程在CPU上运行一会,不断的切换进程周而复始重复运作的。这叫做基于进程切换的分时操作系统,由于CPU的运行速度非常快,切换速度使人类感觉不到,从而使人们有种进程一直在运行的感觉。而CPU会去调用哪一个进程,是由进程的状态来决定的,一个进程可以有多个状态,我们先来说明两个最为核心的状态:阻塞和挂起。
1、阻塞
进程因为等待某种条件就绪,而导致的一种不推进的状态叫做阻塞状态,给人们最直观的感受就是程序卡住了。换句话说,一个进程阻塞,一定是在等待某种所需要的资源就绪的过程。
想象这样一个场景,我们在下载一些资料的时候,如果网断了,CPU还有必要继续调度这个下载进程吗?肯定是没必要了,因为没有意义,此时就会把该进程设置为阻塞状态。那么这个进程是如何等待网络资源就绪的呢?
我们之前讲过,操作系统要管理网卡、磁盘等外设,是一个先描述再组织的过程,操作系统创建多个结构体类型,这里命名为 struct dev ,并把各个外设的属性信息提取填充进来,再用对应的数据结构把他们链接到一起。同样,操作系统管理大量的进程也是一个先描述再组织的过程。
当网络断开时, 需要等待网络资源的进程就会把自己的PCB从CPU的某些特定队列中拿取出来,连接到网卡设备结构体队列的尾部来排队等待网络资源:
此时,再获取到等待的资源之前,该进程不会再被CPU调度。
PCB是可以被维护在不同的队列中的。进程在等待哪种资源,就会被排列到哪种资源的队列中去。再举个例子,当我们在C语言中使用scanf 函数时,运行程序,如果我们不在键盘上输入内容,进程就会处于阻塞状态,并在键盘的结构体中排队等待资源,只有拿到数据时,进程才会再次被CPU调度。
总结:阻塞就是不被CPU调度——一定是因为当前进程需要等待某种资源就绪——一定是进程tesk_struct结构体需要在某种被OS管理的资源下排队。
2、挂起
如果有时候出现了内存资源紧张的情况,而且阻塞进程的PCB被接入到了所需要等待资源的结构体队列中,不被调度。这时,操作系统就会把阻塞进程的代码和数据交换到磁盘中,同时释放其所在内存中占据的空间,从而起到节省内存空间的目的。等到进程所需要的资源就绪的时候,再把该进程的代码和数据加载到内存中,交由CPU调度。
其中把进程的代码和数据由OS暂时性的交换到磁盘中时,称该进程处于挂起状态。全称为阻塞挂起状态。
以下是Linux内核源码中摘抄下来的进程状态:
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};
3、R状态
当一个进程被加载运行时,该进程处于 R 状态。但是进程是 R 状态并不一定代表其一定在CPU上运行。
一个进程是什么状态,一般也看这个进程在哪里排队。 其中在CPU的运行结构体队列中排队等待调度的进程,都是运行状态,即 R 状态。在其他资源结构体队列中排队的进程,都是阻塞状态。
现在我们写一个程序来学习进程的各种状态:
编译运行:
进程明明在运行,为什么却显示成 S 进制状态呢?
现在我们修改一下代码,把打印函数 printf 注释掉:
再来编译运行:
此时,进程的状态就是 R 状态了。
出现这种情况的原因是, printf 函数是向外设打印消息,而外设并不是随时准备就绪的,也就是说进程在执行 printf 函数时,需要在外设的结构体队列中排队等待,当外设资源就绪时,该进程才能被CPU调度,变为 R 状态。其他时间都是阻塞状态, S 状态就是一种阻塞状态。
4、S状态
S 状态是休眠状态,本质上是一种阻塞状态。可以按下 Ctrl+c 终止进程。
5、D状态
D 状态也是一种休眠状态,不可被中断休眠。
在一些进程极多、内存压力极大的情况下,OS是有权利杀掉休眠状态的进程以腾出空间保证其他进程正常运行的,这也是十分合理的。
但是在有一种情况下,这种权力变成了不合理,那就是这个休眠的进程正在磁盘区排队,向磁盘存入数据,如果这个时候OS把该进程杀掉了,就会导致磁盘存储数据出错,万一这个数据还特别重要,就会造成非常严重的后果。
为了解决这个问题,就设计出了 D 状态,处于 D 状态的进程无法被OS杀死,甚至在系统中存在 D 状态的进程时,计算机都没有办法正常关机。只有当 D 状态的进程自己苏醒的时候,这个进程才能被结束。
事实上,一般情况下不会出现 D 状态的进程的,D 状态进程一旦出现,就说明磁盘的空间已经非常的紧张,存储速度非常的慢了,需要力保写入数据的进程活着完成任务,长时间内不能被OS杀死。既然OS都已经需要主动杀死休眠的进程并且磁盘资源已经不够了,可见此时内存的情况也好不到哪里去。当系统中出现了一个 D 状态的进程,就离计算机宕机不远了。
6、T状态
T 状态名为暂停状态,也是一种阻塞状态。我们在调试程序时,让程序在断点处停下来,本质上就是让进程暂停!
6.1、kill指令
查看 kill 指令:
kill -l
在这里主要使用编号为 9、18、19 的命令选项,功能分别为 杀死进程、继续进程、暂停进程。
6.2、暂停进程与继续进程
我们先运行进程,并查看进程状态:
观测到的是 S+ 状态,但实际上程序已经运行了,现在使用指令:
kill -19 [进程PID]
来暂停进程:
此时进程状态就已经变成了 T 。
接着使用指令:
kill -18 [进程PID]
使进程继续进行:
观察到进程状态变回了 S 。
6.3、杀死进程
使用 kill 指令恢复进程后,可以发现进程状态从原来的 S+ 变为了 S ,并且使用 Ctrl+c 已经没有办法结束进程了:
进程状态的 "+" 号表示前台运行,没有 "+" 号就表示后台运行, Ctrl+c 只能结束前台运行的进程。
此时我们需要使用指令:
kill -9 [进程PID]
杀掉进程:
7、X && Z 状态
一般我们再写 main 函数时,会在最后写一个 return0;,这叫做进程退出码,我们使用以下指令可以查到进程退出码:
echo $?
如果一个子进程结束时,立刻退出,父进程是没有机会拿到退出结果的。所以在Linux中,进程退出时,一般不会立即彻底退出,而是要维持一个 Z 状态,也叫僵尸状态,方便后续父进程读取该子进程的退出结果。
我们编写以下程序:
运行并查看进程:
可以看到父子进程都已经在运行之中,只不过显示出来的是 S+ 状态。
现在我们杀掉子进程,再来观察子进程的状态:
此时,子进程变为 Z 状态,即僵尸状态。
如果我们不去主动回收 Z 状态的进程,那么该进程就会一直存在,操作系统就会一直维护该进程的PCB,占据内存的空间,可以理解为内存泄漏,所以僵尸进程必须要回收,具体回收的方法以后会详细讲解。
关于进程概念的相关内容就讲到这里,希望同学们多多支持,如果有不对的地方欢迎大佬指正,谢谢!
相关文章:
【Linux】进程概念
目录 一、基本概念 二、查看进程 三、系统调用获取进程标示符 1、获取自己的PID 2、获取父进程的PID 四、创建进程 1、初识fork 2、使用fork的方式 五、进程状态 1、阻塞 2、挂起 3、R状态 4、S状态 5、D状态 6、T状态 6.1、kill指令 6.2、暂停进程与继续进程 …...
使用pyinstaller库打包exe时显示KeyError怎么办
PyInstaller是一个Python库,用于将Python应用程序转换为独立的可执行文件(executable)文件,支持多平台。它可以将Python解释器、依赖的库和脚本打包成一个单独的可执行文件,从而使应用程序可以独立运行,而无…...
k8s新增节点机器,无法拉取和推送镜像的解决方案
1、首先检查配置,查看镜像仓库是否已授权,若无授权,则进行授权。 命令:cat /etc/systemd/system/docker.service.d/docker-options.conf内容如果有这样一句就是已经授权,如果没有,就需要把这句加进去&…...
测试报告踩坑的点
测试报告作为测试人员的核心输出项,是体现自己工作价值的重要承载工具,需要我们认真对待,所以我们要重视测试报告的输出,那么在编写测试报告的时候,我们有哪些点需要注意的呢? 01 不要乱用模板 很多测试新人在编写测试…...
【Java】创建多线程的四种方式
一、方式1:继承Thread类 步骤: 创建一个继承于Thread类的子类重写Thread类的run()方法 ----> 此线程执行的操作声明在方法体中创建当前Thread子类的对象通过实例对象调用start()方法,启动线程 ----> Java虚拟机会调用run()方法 注意…...
【数据结构】队列的接口实现(附图解和源码)
队列的接口实现(附图解和源码) 文章目录队列的接口实现(附图解和源码)前言一、定义结构体二、接口实现(附图解源码)1.初始化队列2.销毁队列3.队尾入队列4.判断队列是否为空5.队头出队列6.获取队列头部元素7…...
日本知名动画公司东映动画加入 The Sandbox 元宇宙
与 Minto 合作将东映动画的 IP 呈现在元宇宙。 The Sandbox 很荣幸能与东映动画合作,与 Minto 携手在 The Sandbox 元宇宙中创建基于东映动画 IP 的相关体验。 作为日本动画的先驱,东映动画制作了日本最大和世界领先的动画作品,包括《龙珠》、…...
QuickHMI Hawk R3 Crack
基于网络的 SCADA / HMI 系统 QuickHMI Hawk R3 QuickHMI是一个 100% 基于网络的SCADA/HMI 系统。 得益于HTML5、SVG和Javascript等现代网络技术,可视化可以在任何当前浏览器和设备中显示。作为浏览器的替代品,可以使用“独立查看器”和移动应用程序。 Q…...
【C语言】寻找隐藏字母游戏
编程实现一个游戏程序,会将连续三个字母中的一个隐去,由玩家填写隐去的那个字母,如屏幕上显示A ? C,则玩家需要输入B;屏幕上显示?B C,则玩家需要输入A。记录玩家完成20次游戏的时间以及正确率。…...
【C++】list 相关接口的模拟实现
list 模拟实现回顾准备构造析构函数的构造构造方法析构方法赋值运算符重载容量相关接口元素获取元素修改相关接口push 、popinserterase清空交换迭代器 **(重点)迭代器基本概念迭代器模拟实现回顾 在上一篇博客中我们大致了解了 list 相关接口的使用方法…...
快速找到外贸客户的9种方法(建议收藏)
所有外贸企业想要做好外贸出口的头等大事,就是要快速的找到优质的外贸客户和订单,没有订单的达成,所有的努力都是图劳,还有可能会陷入一种虚假的繁荣,每天都很忙,但是没有结果。今天,小编就来分…...
TCP状态转换
欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起探讨和分享Linux C/C/Python/Shell编程、机器人技术、机器学习、机器视觉、嵌入式AI相关领域的知识和技术。 TCP状态转换专栏:《Linux从小白到大神》《网络编程》 TCP状态转换示意图如下 针对上面的示…...
3500年里,印度被11个文明征服
转自:3500年里,印度被11个文明征服,如今看似统一,实际上却是缝合怪 (qq.com)今天的印度是亚洲第二大国,南亚第一大国,世界第二人口大国。如果我们将时间线拉长,纵观历史的长河,就会惊…...
Java编程问题top100---基础语法系列(一)
Java编程问题top100---基础语法系列一一、Java 操作符实质二、将InputStream转换为String使用IOUtils自己写轮子三、将数组转换为List四、如何遍历map对象使用For-Each迭代entries(方法一)使用For-Each迭代keys和values(方法二)使…...
【C#基础】C# 异常处理操作
序号系列文章6【C#基础】C# 常用语句讲解7【C#基础】C# 常用数据结构8【C#基础】C# 面向对象编程文章目录前言1,异常的概念2,处理异常3,自定义异常4,编译器异常结语前言 🌷大家好,我是writer桑,…...
系统分析师---操作系统思维导图
进程管理(5星) 进程与线程:共享:内存地址空间、代码、数据、文件等不能共享:独立的cpu运行上下文和栈指针、寄存器 信号量与PV操作:信号量,一种特殊的变量分为:信号量可以表示资源数…...
Linux | Ubuntu20.04系统使用命令从移动硬盘/U盘拷贝文件到服务器上
*确认自己移动硬盘、U盘的格式,本文为exfat格式STEP1:把移动硬盘插到Ubuntu系统的主机上查看disk默认位置#查看移动硬盘/U盘在哪个位置命令 fdisk -l #查询后出现了包含电脑系统的所有硬盘查看最后的位置,我的显示为Device, 位置为 /dev/sdb1…...
【经验总结】10年的嵌入式开发老手,到底是如何快速学习和使用RT-Thread的?
【经验总结】一位近10年的嵌入式开发老手,到底是如何快速学习和使用RT-Thread的? RT-Thread绝对可以称得上国内优秀且排名靠前的操作系统,在嵌入式IoT领域一直享有盛名。近些年,物联网产业的大热,更是直接将RT-Thread这…...
一起Talk Android吧(第五百零九回:约束布局中的组功能一)
文章目录功能介绍使用方法GroupLayer对比总结各位看官们大家好,上一回中咱们说的例子是"多层布局功能",这一回中咱们说的例子是"约束布局中的组功能"。闲话休提,言归正转, 让我们一起Talk Android吧! 功能介…...
2023安徽省“中银杯”职业技能大赛“网络安全” 项目比赛任务书
2023安徽省“中银杯”职业技能大赛“网络安全” 项目比赛任务书2023安徽省“中银杯”职业技能大赛“网络安全” 项目比赛任务书A模块基础设施设置/安全加固(200分)A-1:登录安全加固(Windows, Linux)A-2:Ngi…...
观测云产品更新|新增用户访问监测自动化追踪;新增 CDN 质量分析;新增自定义查看器导航菜单等
观测云更新 用户访问监测优化 新增用户访问监测自动化追踪 用户访问监测新增自动化追踪,通过“浏览器插件”的实现方式,使用浏览器记录用户访问行为,创建无代码的端到端测试。更多详情可参考文档【 自动化追踪 】https://docs.guance.com/…...
大数据技术生态全景一览
大数据技术生态全景一览大数据平台ETL数据接入大数据平台海量数据存储大数据平台通用计算大数据平台各场景的分析运算分布式协调服务任务流调度引擎大数据平台ETL数据接入 大数据有很多的产品,琳琅满目。从架构图上就能看出产品很多。这些产品它们各自的功能是什么…...
CI/CD | 深入研究Jenkins后,我挖掘出了找到了摆脱低效率低下的方法
在本系列的第一篇文章中,您已经了解了一些关于如何管理Jenkins的内容,主要是为无序的人带来秩序。在这篇文章中,我将更深入地探讨我效率低下的问题,提出我们工作流中一些安全性、治理和合规性的挑战。这不仅仅是你在网站上或展览横…...
刷LeetCode
文章目录滑动窗口算法1 涉及知识点 :unordered_set 容器2 参数详情3 例题滑动窗口算法 滑动的窗口,每次记录下窗口的状态,再找出符合条件的窗口使用滑动窗口减少时间复杂度 1 涉及知识点 :unordered_set 容器 说明:…...
Spring 大白话系列:工厂
Spring 大白话系列:工厂 “工厂模式,大家都很熟悉了。说到底,就是解除创建对象和使用对象之间的耦合。这东西没啥啊。” 教室里,老师傅听到小明在嘀嘀咕咕的。老师走过去问: “有什么问题呢小明同学?” 小…...
喜讯!华秋电子荣获第六届“蓝点奖”十佳分销商奖
2 月 25 日,由深圳市电子商会主办的2023 中国电子信息产业创新发展交流大会暨第六届蓝点奖颁奖盛典在深圳隆重举行。 图:华秋商城渠道总监杨阳(右三) 深圳市电子商会连续六年举办“蓝点奖”评选活动,旨在表彰对电子信…...
Linux概述
1:Linux概述1.1:操作系统常见操作系统有:Windows、MacOS、Linux。名称描述Windows微软公司研发的收费操作系统。分为两类:用户操作系统、Server操作系统。用户操作系统:win 95、win 98、win NT、win Me、win xp、vista…...
中级嵌入式系统设计师2015下半年上午试题及答案解析
中级嵌入式系统设计师2015下半年上午试题 单项选择题 1、CPU是在______结束时响应DMA请求的。 A.一条指令执行 B.一段程序 C.一个时钟周期 D.一个总线周期 2、虚拟存储体系由______两级存储器构成。 A.主存-辅存 B.寄存器-Cache C.寄存器-主存...
华为OD机试模拟题 用 C++ 实现 - 删除指定目录(2023.Q1)
最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 最多获得的短信条数(2023.Q1)) 文章目录 最近更新的博客使用说明删除指定目录题目输入输出示例一输入输出说明Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为…...
【正点原子FPGA连载】第二十章AXI4接口之DDR读写实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南
1)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id692450874670 3)全套实验源码手册视频下载地址: http://www.openedv.com/thread-340252-1-1.html 第二十章AXI4接口…...
用js做的个人酷炫网站/百度招聘
js算法一、关于排序1.1冒泡排序1.2 快速排序二、反向输出2.1 数组反向输出2.2 字符串反向输出三、数学方法3.1 阶乘的实现3.2 生成斐波那契数列四、回文串五、变量值互换六、计算出现次数6.1 计算字符串里出现最多的字符及次数6.2 计算数组里出现最多的元素及次数一、关于排序 …...
怎么样做网站/seo优化工具
最近因为工作需求原因一直使用VUE框架,作为时下最热门的渐进式框架,开发起来确实非常给力~ 当然一个好的工具也不可能完全对你百依百顺,最近在工作中就遇到了一个问题,经过一下午的奋战终于搞定了,秉承着本熊一贯的无私…...
深圳百姓网/优化网站内容
1.自定义标签 *步骤: **编写一个实现Tag接口的Java类,把页面中的java代码移到这个java类中(标签处理器类) **编写标签库描述符(tld)文件,在tld文件中把标签处理器描述成一个标签。 *作用&…...
elegant wordpress/网站的推广方式有哪些
“转正”、“转型”、“转强” 这是属于中国经济的关键词! 在今年的困境之下,中国经济展现出了强大的韧性,从复产复工,到全面转正,再到世界经济的引擎,一张漂亮的成绩单赢得全球关注。国际货币基金组织&…...
做网站双12促销方案/网站没有友情链接
这个问题。。。。。。很简单,但一直有人问,每次还是细节,算了,直接写个小短文吧。下面是一段Sample代码,我们假设MSI文件被放到了Support Files中,并且通过静默安装方式调用第三方MSI包,msiexec…...
网站空间最便宜/seo专业培训班
定义: 指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。 优点: 1、降低了目标与观…...