一篇文章学习什么是进程(万字解析,超多知识点)
目录
- 进程概念
- 进程控制块-PCB
- PCB的内容分类
- 标识符
- 查看进程信息的方法
- 状态
- fork函数
- 进程状态
- R运行状态(running)
- S睡眠状态(sleeping)
- D磁盘休眠状态(Disk sleep)
- T停止状态(stopped)
- X死亡状态(dead)
- 优先级
- 进程优先级
- 基本概念
- PRI和NI
- top-查看进程优先级的命令
- 程序计数器
- 内存指针
- 上下文数据
- I/O状态信息
- 记账信息
- 特殊进程
- Z(zombie)-僵尸进程
- 僵尸进程的作用
- 僵尸进程的危害
- 孤儿进程
- 关于进程的其他概念
- 并行和并发的区别
- 程序地址空间
- 实验环境
- c语言角度的内存空间
- 进程地址空间
- mm_struct
- mm_struct的理解
- 页表
- 页表的作用
- 写时拷贝
- 概念
- 解释代码现象
- 为什么需要写时拷贝
- 总结
进程概念
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
进程控制块-PCB
进程信息都是放在一个叫进程控制块即PCB(process control block),可以简单地理解为进程数据集合。
在操作系统的学习中,我们知道了操作系统要管理进程,就要做到先描述,再使用,在Linux中内核描述进程的结构体叫做task_struct。
PCB的内容分类
标识符
标识符:描述进程的唯一标识符,用来区别其他进程。
首先我们来认识一个命令叫做ps-显示进程状态
语法:ps [参数]
常用参数参考详情
我们可以看到有PPID和PID,PID是本进程的标识符,PPID是父进程的标识符。
查看进程信息的方法
- 上面的ps命令
- 通过/proc系统文件夹来查看
- 通过系统调用来获取进程标识符,getpid()和getppid()
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{printf("pid: %d\n", getpid());printf("ppid: %d\n", getppid());return 0;
}
状态
状态:任务状态、退出代码,退出信号等等
fork函数
首先我们认识一下系统调用接口fork-创建一个进程
#include<stdio.h>#include<unistd.h>#include<sys/types.h>int main(){pid_t id=fork();if(id > 0){//fatherprintf("pid:%d,ppid:%d\n",getpid(),getppid());sleep(5);}else if(id == 0){//childprintf("pid:%d,ppid:%d\n",getpid(),getppid());sleep(5);}else{perror("fork");return 1;}return 0;}
在fork创建一个新进程后,子进程执行和父进程相同的代码,我们往往通过它的返回值进行分流,使父子进程执行不同的代码。
进程状态
首先我们看看Linux的源代码
我们可以通过源代码看出task_struct中通过一个字符指针数组来进行进程状态分类。
我着重介绍R、S、D、t、T、Z这几个状态。
R运行状态(running)
R运行状态:表示进程在运行中或者在运行队列中(可被cpu调度),不一定正在运作。
我们写一个死循环看看。
#include<stdio.h>
int main()
{while(1){}return 0;
}
一定要记住,进程是R状态不一定在运行!!!
S睡眠状态(sleeping)
S睡眠状态:表示进程正在休眠不会被cpu调度直到被唤醒,此状态可以被杀掉。
#include<stdio.h>
#include<unistd.h>
int main()
{sleep(10);return 0;
}
此状态的意义是在进程需要某种资源才能继续跑下去时,我们将进程进行睡眠,节约cpu资源,在条件满足时将进程唤醒。
D磁盘休眠状态(Disk sleep)
D磁盘休眠状态:也叫不可中断睡眠状态,相比较S状态,在D状态时不能被杀掉(OS也不行)。
此状态不好实现,我们就讲讲为什么会有一个和S状态如此相像的D状态。
在一个进程向硬盘写入数据时,进程应该进入睡眠模式等待硬盘回应,如果此时内存空间严重不足时,OS可能会干掉一些S状态的进程分配给活跃的进程,此时就导致了一个问题,那就是如果硬盘在写入数据出现错误时它向进程询问该怎么办,但是此时进程已经被OS干掉了,就会陷入一个尴尬的场景。
那么上面描述中,是谁的错?
答案是都没错
进程:我与硬盘进行IO时进入睡眠模式节约cpu资源结果被cpu干掉了,我能怎么办?
硬盘:我在存入数据本来就有几率出现错误,但是我回去问进程该怎么办,它一直不回答,我能怎么办?
OS:内存资源已经非常少了,我干掉一些偷懒的进程把资源分配给活跃的进程,我有什么错。
所以为了避免上面这种情况,我们需要一个在睡眠状态不能被干掉的状态,那就是D状态。
T停止状态(stopped)
T停止状态:可以通过发送SIGSTOP信号让进程停止,可以通过发送SIGCONT信号让进程继续运行。
这里借用R状态的代码
首先进程处于R状态,kill命令可以给指定进程发信号,在我们向进程发送SIGSTOP时,我们可以看到进程的STAT从R+变成了T,在发送SIGCONT信号后STAT又变成了R。
信号有关的命令以后细嗦,先放个图了解一下。
X死亡状态(dead)
X死亡状态:这个状态只是一个返回状态,我们不能从ps中的STAT列表中看到此状态。
优先级
优先级:代表进程被cpu调度的优先级。
进程优先级
基本概念
- cpu分配资源给进程的先后顺序,就是进程的优先级
- 进程的优先级高,优先被cpu调度。
- 将不重要的进程优先级降低可以提高cpu资源利用。
我们来看看ps -l中的信息
其中与进程优先级有关的数据就是PRI和NI
PRI和NI
PRI:代表进程的优先级,越低优先级越高。
NI:代表进程的nice值
PRI很好理解,那NI所代表的nice值是什么呢?
- nice值我们可以简单地理解为PRI的修正数据
- PRI越低优先级越高,那引入nice值后:(new)PRI=(old)PRI+NI
- nice值的范围为-20~19。
- 我们通过修改NI调整一个进程的优先级。
top-查看进程优先级的命令
- top(有点类似Windows下的任务管理器)
- 进入top输入“r”->输入修改进程的pid->输入nice值(不管是降低还是增加nice值,都需要sudo提高权限)
修改前
输入“r”
输入nice值
修改成功
我们可以看出**(new)PRI=(old)PRI+NI**
程序计数器
程序计数器:程序中即将被执行的下一行代码的地址
这就是为什么程序知道自己的该怎样执行代码。
内存指针
内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。
进程可以通过内存指针找到自己的代码和数据以及共享内存块。
上下文数据
上下文数据:进程执行时寄存器中的数据
我们如何来理解这个上下文数据呢?
首先我们要明白cpu运行进程1执行到i++时,cpu需要将i取到寄存器中进行自加一,然后再写入到内存中,Linux中进程是通过时间片算法切换运行,达到一个并发的效果,但是如果cpu刚将i++完成准备从寄存器中把i写入到内存时进程1的时间片到了,cpu就会切换下一个进程,而cpu的寄存器是有限的,所以进程1在寄存器中的数据就会被覆盖,如果下次轮到进程1的时间片时,cpu又会重复上述过程导致cpu资源浪费,所以为了避免这种情况,我们需要将cpu寄存器中的数据在切片前保存到上下文数据中,这样的话,下次cpu跑该进程时先把上下文数据读取到寄存器中再执行下一步命令。
I/O状态信息
I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
记账信息
记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
特殊进程
Z(zombie)-僵尸进程
- 僵尸进程是一种特殊的状态。当进程退出时并且父进程没有读取进程的退出信息时,就会一直保持Z僵尸模式直到父进程读取。
- 僵尸进程的生命周期为进程退出,父进程存在并读取前。
不多bb,上代码
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{pid_t id=fork();if(id == 0){//childprintf("i am child,pid:%d,ppid:%d\n",getpid(),getppid());sleep(5);}else if(id > 0){//fatherprintf("i am father,pid:%d,ppid:%d\n",getpid(),getppid());sleep(30);}else {perror("fork");return 1;}return 0;
}
僵尸进程的作用
帮助父进程了解子进程的任务完成情况以及退出信息。,比如,一个人突然死了,有人发现后选择报警肯定不会乱动尸体(除了凶手),警察发现尸体后也会保留案发现场,这些都是因为尸体和现场会留下信息让警察去侦察这个人是怎么死的。
僵尸进程的危害
进程的退出信息是保存在PCB中,如果父进程一直不读取子进程退出信息,这个PCB就会一直存在浪费内存资源。
孤儿进程
- 在子进程退出父进程未读取时,会产生僵尸进程,那么如果父进程比子进程先退出,那子进程的退出信息又改由谁来回收呢?
- 父进程先退出,子进程就会变成孤儿进程,然后被1号进程领养,从而1号进程负责回收子进程的退出信息。
这个代码与僵尸进程的代码相似。
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{pid_t id=fork();if(id == 0){//childprintf("i am child,pid:%d,ppid:%d\n",getpid(),getppid());sleep(30);}else if(id > 0){//fatherprintf("i am father,pid:%d,ppid:%d\n",getpid(),getppid());sleep(5);}else {perror("fork");return 1;}return 0;
}
关于进程的其他概念
- 竞争性:系统中进程数目众多,cpu资源只有少量,所以进程会竞争cpu资源的使用权,操作系统为了使进程合理使用cpu资源,便有了优先级。
- 独立性:多进程运行会独享很多资源,各个进程运行中互不干扰。
- 并行:多个进程在多个cpu下同时运行。
- 并发:多个进程在单个cpu下采用进程切换的方式,在一个时间段中,使多个进程得到推进。
并行和并发的区别
并行是每个进程都有自己的cpu,在每一刻多个进程同时运行,而并发是很多进程轮流使用一个cpu资源,例如Linux采用时间片切换的算法,使多个进程在一个时间段中看起来像是同时进行,系统下进程数目往往远大于cpu资源,所以并发在大多数场景下更为合理。
程序地址空间
实验环境
kernel 2.6.32
32位平台
c语言角度的内存空间
相信大家在学习c语言的时候一定听过什么内存分为栈区堆区等等栈区向下生长、堆区向上生长,也看过下面这一副图。
我们可以通过一段代码来验证一下是不是如此。
#include<stdio.h>
#include<stdlib.h>
static int init_value=10; //static修饰的全局变量只能在本文件中访问
static int uninit_value;int main(int argc)
{int i=0;int* pi=malloc(sizeof(int));printf("%p\n",&argc);printf("%p\n",&i);printf("%p\n",pi);printf("%p\n",&uninit_value);printf("%p\n",&init_value);printf("%p\n",main);return 0;
}
我们可以看出确实如此,接下来我们看看另一段代码
#include<stdio.h>#include<unistd.h>#include<sys/types.h>int global_val=10;int main(){pid_t id=fork();if(id > 0){//fatherprintf("i am father,%p,%p\n",&global_val,main);}else if(id == 0){//childprintf("i am child,%p,%p\n",&global_val,main);}else{perror("fork");return 1;}return 0;}
通过运行结果,我们可以得到一个结论,那就是在父子进程未对数据进行修改时,子进程的代码和数据是和父进程共享的。
接下来,我们在上述代码的基础上进行一些小小的改变。
#include<stdio.h>#include<unistd.h>#include<sys/types.h>int global_val=10;int main(){pid_t id=fork();if(id > 0){//fathersleep(5)printf("i am father,%p,%d\n",&global_val,global_val);}else if(id == 0){//childglobal_val=20;printf("i am child,%p,%d\n",&global_val,global_val);}else{perror("fork");return 1;}return 0;}
注意这里让父进程休眠了5秒,子进程将global_val的值改成了20,见证奇迹的时候到了。
我们可以看到父子进程的val不一样,但是他们的地址却是一样的,这到底是为什么呢?
- 首先,他们的val不一样说明父子进程输出的val绝对不是同一个变量。
- 其次,他们的地址一样说明这个打印出来的地址并不是真正的物理地址。
那这个地址到底是什么东西呢?
- 在Linux下,这个地址叫做虚拟地址,听名字我们就知道了它不是真正的物理地址。
- 注意我们通过C/C++打印看到的地址统统都是虚拟地址!用户看不到物理地址,物理地址由操作系统管理。
进程地址空间
有人看到这个标题肯定会有疑问,你怎么一会一个程序地址空间,一会一个进程地址空间呢?其实严格上讲,这个应该叫做进程地址空间。
那进程地址空间到底是什么样子的呢?其实它也是一个结构体,话不多说上源码。
mm_struct
struct mm_rss_stat {atomic_long_t count[NR_MM_COUNTERS];
};
/* per-thread cached information, */
struct task_rss_stat {int events; /* for synchronization threshold */int count[NR_MM_COUNTERS];
};
#else /* !USE_SPLIT_PTLOCKS */
struct mm_rss_stat {unsigned long count[NR_MM_COUNTERS];
};
#endif /* !USE_SPLIT_PTLOCKS */struct mm_struct {struct vm_area_struct * mmap; /* list of VMAs */struct rb_root mm_rb;struct vm_area_struct * mmap_cache; /* last find_vma result */
#ifdef CONFIG_MMUunsigned long (*get_unmapped_area) (struct file *filp,unsigned long addr, unsigned long len,unsigned long pgoff, unsigned long flags);void (*unmap_area) (struct mm_struct *mm, unsigned long addr);
#endifunsigned long mmap_base; /* base of mmap area */unsigned long task_size; /* size of task vm space */unsigned long cached_hole_size; /* if non-zero, the largest hole below free_area_cache */unsigned long free_area_cache; /* first hole of size cached_hole_size or larger */pgd_t * pgd;atomic_t mm_users; /* How many users with user space? */atomic_t mm_count; /* How many references to "struct mm_struct" (users count as 1) */int map_count; /* number of VMAs */spinlock_t page_table_lock; /* Protects page tables and some counters */struct rw_semaphore mmap_sem;struct list_head mmlist; /* List of maybe swapped mm's. These are globally strung* together off init_mm.mmlist, and are protected* by mmlist_lock*/unsigned long hiwater_rss; /* High-watermark of RSS usage */unsigned long hiwater_vm; /* High-water virtual memory usage */unsigned long total_vm, locked_vm, shared_vm, exec_vm;unsigned long stack_vm, reserved_vm, def_flags, nr_ptes;unsigned long start_code, end_code, start_data, end_data;unsigned long start_brk, brk, start_stack;unsigned long arg_start, arg_end, env_start, env_end;unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv *//** Special counters, in some configurations protected by the* page_table_lock, in other configurations by being atomic.*/struct mm_rss_stat rss_stat;struct linux_binfmt *binfmt;cpumask_t cpu_vm_mask;/* Architecture-specific MM context */mm_context_t context;/* Swap token stuff *//** Last value of global fault stamp as seen by this process.* In other words, this value gives an indication of how long* it has been since this task got the token.* Look at mm/thrash.c*/unsigned int faultstamp;unsigned int token_priority;unsigned int last_interval;/* How many tasks sharing this mm are OOM_DISABLE */atomic_t oom_disable_count;unsigned long flags; /* Must use atomic bitops to access the bits */struct core_state *core_state; /* coredumping support */
我们之前提到操作系统要进行管理就要**“先描述,再组织”**,内存管理也不例外,mm_struct就是操作系统用来进行内存管理的结构体。
那么结构体里面的变量都是什么意思为什么操作系统可以通过这些变量来进行内存管理呢?
首先,我们要认识一个问题,那就是我们是如何管理地球上的土地(内存)的,各个国家通过划分边界线的方式来确定自己可以使用的土地,而这些国家通过气候环境等等因素将自己的土地划分成住宅区、农耕区、工业区,我们往往通过尺度单位(记录起始位置+结束位置)来划分土地,而只要边界确定好了,我们就可以通过边界来确认自己使用土地是否合法。
mm_struct的理解
对应到操作系统来说,划分区域是为了更好地管理内存,提高管理内存效率,而mm_struct中的一个个unsigned long变量就是每个区域的起始位置和结束位置,操作系统可以采用基地址+偏移量的方法来判断内存访问和申请是否合法。
页表
我们都知道mm_struct中的地址都是虚拟地址不是真正的物理地址,那么操作系统通过mm_struct来管理真正的物理内存呢?
接下来我们要引出一个概念叫做页表。
页表是一种特殊的数据结构,放在系统空间的页表区,存放逻辑页与物理页帧的对应关系。 每一个进程都拥有一个自己的页表,PCB表中有指针指向页表。
页表的作用
- 存储虚拟地址和物理地址的映射,进程可以通过页表将虚拟地址找到物理地址并进行数据的增删查改。
- 不会将真正的物理地址暴露给用户,保护内存。
写时拷贝
概念
写时拷贝是一种可以推迟甚至免除拷贝数据的技术。 内核此时并不复制整个进程地址空间,而是让父进程和子进程共享同一个拷贝。 只有在需要写入的时候,数据才会被复制,从而使各个进程拥有各自的拷贝。
解释代码现象
现在可以来解释这个神奇的结果了。
我们通过图来说明上面的代码问题。
- 在父子进程fork子进程时,子进程复制父进程的数据形成task_struct和mm_struct以及页表,此时父子进程的global_val指向同一个物理地址。(子进程拥有自己的task_struct和mm_struct以及页表,但是内容与父进程相同)
- 当子进程执行到global_val=20时就会发生写时拷贝,子进程会在物理内存上申请一个新的空间用来存放自己的global_val变量,接着子进程只需把页表中对应的物理内存修改成新的物理内存地址不需要修改虚拟内存地址,所以我们打印出来的地址一样。
为什么需要写时拷贝
因为进程之间具有独立性,就算是父子进程也不能影响其他进程的数据,并且在创建子进程时不开辟新的物理内存,等到需要时在申请空间,可以高效地使用内存空间。
总结
- 子进程的创建实质就是task_struct和mm_struct以及页表的创建,拷贝父进程的数据。
- 进程地址空间(mm_struct和页表)避免了系统级别的越界问题即错误访问物理内存。
- 每个进程对待内存的看法都一样(因为mm_struct一样)。
写在最后:文中Linux源码来自Linux源码,创作不易,如果这篇文章对你有帮助,希望大佬们三连支持。
相关文章:

一篇文章学习什么是进程(万字解析,超多知识点)
目录进程概念进程控制块-PCBPCB的内容分类标识符查看进程信息的方法状态fork函数进程状态R运行状态(running)S睡眠状态(sleeping)D磁盘休眠状态(Disk sleep)T停止状态(stopped)X死亡…...

第01章_数据库概述
第01章_数据库概述 讲师:尚硅谷-宋红康(江湖人称:康师傅) 官网:http://www.atguigu.com 1. 为什么要使用数据库 持久化(persistence):把数据保存到可掉电式存储设备中以供之后使用。大多数情况下&#x…...

我所理解的高通UEFI之display的流程和移植
UEFI的流程UEFI跟uboot一样在OS加载启动之前,正确的指定启动服务,并向内核传递信息,代替原先的uboot。它包含了上电、驱动实现,以及os环境的建立和应用程序(类似于fastboot)。这个os是UEFI自己独立运行独有…...

iozone -a fsync: I/O error
iozone -a fsync: I/O error iozone: interrupted exit iozone 问题表现是手机老化后重启不开机。检查不开机Log,发现/data/system/packages.xml文件有损坏,pull 离线日志,发现出问题前后的日志也不能pull,pull出来的离线日志解压…...

Element UI框架学习篇(五)
Element UI框架学习篇(五) 1 准备工作 1.1 在zlz包下创建数据传输对象类EmpDTO package com.zlz.dto;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;//根据前台来的 Data public class EmpDTO {private String name;private Stri…...

SpringBoot 全局异常处理用法及原理
SpringBoot 全局异常处理用法及原理 Springboot或springMVC项目中, 我们一般会设置一个全局异常处理, 来对异常进行兜底。 业务代码执行过程中抛出的异常, 如果业务逻辑没有主动捕获,那么异常就会一直往上抛,最后进入…...

浏览器中HTTP请求流程是如何处理的
HTTP 是一种允许浏览器向服务器获取资源的协议,是 Web 的基础,通常由浏览器发起请求,用来获取不同类型的文件,例如 HTML 文件、CSS 文件、JavaScript 文件、图片、视频等。 浏览器端发起 HTTP 请求流程: 1. 构建请求…...

【Pytorch项目实战】之语义分割:U-Net、UNet++、U2Net
文章目录博主精品专栏导航一、前言1.1、什么是图像分割?1.2、语义分割与实例分割的区别1.3、语义分割的上下文信息1.4、语义分割的网络架构二、网络 数据集2.1、经典网络的发展史(模型详解)2.2、分割数据集下载三、算法详解3.1、U-Net3.1.1、…...

七、插件机制
Interceptor MyBatis 插件模块中最核心的接口就是 Interceptor 接口,它是所有 MyBatis 插件必须要实现的接口,其核心定义如下: public interface Interceptor {// 插件实现类中需要实现的拦截逻辑Object intercept(Invocation invocation) …...

kmp算法
前缀函数 π[i]maxk0,⋯,i{k∣s[0,⋯,k−1]s[i−(k−1),⋯,i]}\pi\left[i\right] \max\limits_{k 0,\cdots, i}\left\{k|s\left[0,\cdots,k-1\right] s\left[i-\left(k-1\right) ,\cdots, i\right]\right\} π[i]k0,⋯,imax{k∣s[0,⋯,k−1]s[i−(k−1),⋯,i]} 简单来说…...

【Python】正则表达式简单教程
0x01 正则表达式概念及符号含义 掌握正则表达式,只需要记住不同符号所表示的含义,以及对目标对象模式(或规律)的正确概括。 1、基础内容 字符匹配 在正则表达式中,如果直接给出字符,就是精确匹配。\d 匹…...

SAP ABAP Odata
GetEntity和GetEntitys GetEntitys 创建Odata Project 导入结构 选择需要的字段 设定Key 勾选字段的creatable、updatable、sortable、nullable、filterable属性值。 再依上述步骤创建ZPOITEM结构和实体集 3. 创建ZPOHEADER和ZPOITEM的Association 两个实体集的关联字段&…...

Android native ASAN 排查内存泄漏
一、概述 android 对native - c/c 的调试和排查是比较难受的一件事。我看周遭做window , linux 甚至ios的调试排查起c的代码都比较方便。习惯了app开发去熟悉native是各种痛苦,最主要是排查问题上。后续有时间打算整理下native 的错误排查使用ÿ…...

Django项目开发
一.认识NoSQL 1.SQL 关系型数据库 结构化: 定义主键,无符号型数据等关联的:结构化表和表之间的关系通过外键进行关联,节省存储空间SQL查询:语法固定 SELECT id,name,age FROM tb_user WHERE id1 ACID 2.NoSQL 非关系型数据库 Re…...

Debezium系列之:深入理解Debezium Server和Debezium Server实际应用案例详解
Debezium系列之:深入理解Debezium Server和Debezium Server实际应用案例详解 一、认识Debezium Server二、下载Debezium Server三、解压Debezium Server四、查看Debezium Server目录五、Debezium Server配置六、Debezium Server启动输出样式七、源配置八、格式配置九、Transfo…...

IDE2022源码编译tomcat
因为学习需要,我需要源码编译运行tomcat对其源码进行一个简单的追踪分析。由于先前并未接触过java相关的知识,安装阻力巨大。最后请教我的开发朋友才解决了最后的问题。将其整理出来,让大家能够快速完成相关的部署。本文仅解决tomcat-8.5.46版…...

214 情人节来袭,电视剧 《点燃我温暖你》李峋同款 Python爱心表白代码,赶紧拿去用吧
大家好,我是徐公,六年大厂程序员经验,今天为大家带来的是动态心形代码,电视剧 《点燃我温暖你》同款的,大家赶紧看看,拿去向你心仪的对象表白吧,下面说一下灵感来源。 灵感来源 今天ÿ…...

数据库范式
基本概念 函数依赖 x→yx\rightarrow yx→y,当确定xxx的时候,yyy也可以确定 例: 学号→\rightarrow→姓名,当知道了学号,就知道了学生姓名 学号,课程号→\rightarrow→成绩,当知道了学号和课程号ÿ…...

CUDA中的底层驱动API
文章目录CUDA底层驱动API1. Context2. Module3. Kernel Execution4. Interoperability between Runtime and Driver APIs5. Driver Entry Point Access5.1. Introduction5.2. Driver Function Typedefs5.3. Driver Function Retrieval5.3.1. Using the driver API5.3.2. Using …...

【博客616】prometheus staleness对PromQL查询的影响
prometheus staleness对PromQL查询的影响 1、prometheus staleness 官方文档的解释: 概括: 运行查询时,将独立于实际的当前时间序列数据选择采样数据的时间戳。这主要是为了支持聚合(sum、avg 等)等情况,…...

多传感器融合定位十三-基于图优化的建图方法其二
多传感器融合定位十二-基于图优化的建图方法其二3.4 预积分方差计算3.4.1 核心思路3.4.2 连续时间下的微分方程3.4.3 离散时间下的传递方程3.5 预积分更新4. 典型方案介绍4.1 LIO-SAM介绍5. 融合编码器的优化方案5.1 整体思路介绍5.2 预积分模型设计Reference: 深蓝学院-多传感…...

linux 服务器线上问题故障排查
一 线上故障排查概述 1.1 概述 线上故障排查一般从cpu,磁盘,内存,网络这4个方面入手; 二 磁盘的排查 2.1 磁盘排查 1.使用 df -hl 命令来查看磁盘使用情况 2.从读写性能排查:iostat -d -k -x命令来进行分析 最后一列%util可以看到每块磁盘写入的程度,而rrqpm/s以及…...

Sandman:一款基于NTP协议的红队后门研究工具
关于Sandman Sandman是一款基于NTP的强大后门工具,该工具可以帮助广大研究人员在一个安全增强型网络系统中执行红队任务。 Sandman可以充当Stager使用,该工具利用了NTP(一个用于计算机时间/日期同步协议)从预定义的服务器获取并…...

【SSL/TLS】准备工作:HTTPS服务器部署:Nginx部署
HTTPS服务器部署:Nginx部署1. 准备工作2. Nginx服务器YUM部署2.1 直接安装2.2 验证3. Nginx服务器源码部署3.1 下载源码包3.2 部署过程4. Nginx基本操作4.1 nginx常用命令行4.2 nginx重要目录1. 准备工作 1. Linux版本 [rootlocalhost ~]# cat /proc/version Li…...

微搭低代码从入门到精通11-数据模型
学习微搭低代码,先学习基本操作,然后学习组件的基本使用。解决了前端的问题,我们就需要深入学习后端的功能。后端一般包括两部分,第一部分是常规的数据库的操作,包括增删改查。第二部分是业务逻辑的编写,在…...

【算法基础】前缀和与差分
😽PREFACE🎁欢迎各位→点赞👍 收藏⭐ 评论📝📢系列专栏:算法💪种一棵树最好是十年前其次是现在1.什么是前缀和前缀和指一个数组的某下标之前的所有数组元素的和(包含其自身&#x…...

LTD212次升级 | 官网社区支持PC端展示 • 官网新增证件查询应用,支持条形码扫码查询
1、新增证件查询应用,支持条形码扫码查询; 2、新增用户社区PC端功能; 01证件查询应用 1、新增证件查询应用功能 支持证件信息录入、打印功能,支持条形码扫码识别。 后台管理操作路径:官微中心 - 应用 - 证件查询 …...

【安全】nginx反向代理+负载均衡上传webshell
目录 一、负载均衡反向代理下上传webshell Ⅰ、环境搭建 ①下载蚁剑,于github获取官方版: ②下载docker&docker-compose ③结合前面启动环境 ④验证 负载均衡下webshell上传 一、负载均衡反向代理下上传webshell 什么是反向代理? 通常的代…...

线程池框架
这是之前有做的一个可以接受用户传入任意类型的任务函数和任意参数,并且能拿到任务对应返回值的一个线程池框架,可以链接成动态库,用在相关项目里面。一共实现了两版,都是支持fixed和cached模式的,半同步半异步的&…...

【TCP的拥塞控制】基于窗口的拥塞控制
TCP的拥塞窗口CWND大小和传输轮次n的关系如下所示。(本题10分) cwnd12481632333435363738394041422122232425261248N1234567891011121314151617181920212223242526 问题: (1)慢开始阶段的时间间隔?&#…...