【Linux学习笔记】进程概念(中)
- 1. 操作系统的进程状态
- 2. Linux操作系统的进程状态
- 3. 僵尸进程
- 4. 孤儿进程
- 5. 进程优先级
- 5.1. 优先级是什么和为什么要有优先级
- 5.2. Linux中的进程优先级
- 6. 进程切换
- 7. 环境变量
- 7.1. 环境变量的认识
- 7.2. 环境变量相关的命令
- 7.3. 环境变量和本地变量
- 7.4. 命令行参数
- 7.5. 获取环境变量
- 7.6. 环境变量学习小总结
1. 操作系统的进程状态
- 运行状态
程序运行到内存的时候,可以称该程序是一个进程。操作系统为该进程创建了一个PCB,是给CPU管理使用的。进程有很多,而CPU只有一个,所以一旦进程多了,就需要等待。CPU中有一个运行队列,当进程处于运行队列的时候,可以称该进程处于运行状态。
- 阻塞状态
当进程1想要访问磁盘的时候,磁盘还有其他进程尚未处理完毕,所以让进程1进入磁盘的PCB的等待队列中,此时称进程1的状态为阻塞状态。假设不把进程1放进等待队列中,那么进程1只能处于CPU的运行队列中,就是让CPU等待,这是很不合理的。因为CPU的处理速度很快,而磁盘的处理速度相对于CPU比较慢,不可能等待处理速度慢的磁盘。
例如你电脑的硬件处理速度很烂,比如说是磁盘,那么当你访问磁盘的时候会有卡顿,这个卡顿其实可以理解为所谓的阻塞状态。
- 挂起状态
如上图所示,这里有4个进程,都是要访问磁盘的,进程1访问磁盘,磁盘尚未处理结束,需要进程1等待,那么此时进程1进入阻塞状态。然后进程2也要访问磁盘,进程3也是,进程4也是,…,那么2、3、4进程都是阻塞状态。此时处于阻塞状态的进程太多了,处于阻塞状态,意味着内存里面都要保存着进程的相关数据,然而此时内存空间不足了,于是操作系统就把其他处于阻塞状态的2、3、4进程的相关数据放到磁盘的某个空间存储,用以减少内存空间的开销。这样的进程的状态称为挂起状态。如下图所示。
进程的相关数据被保存了起来,但是进程依然存在于内存,这样减少了内存空间的开销,而进程也因PCB的存在等待被重新唤回。
2. Linux操作系统的进程状态
Linux操作系统的进程状态一般有以下7种状态,下面逐一讲解一下。
- 运行状态
Linux操作系统进程的运行状态的字母是R。下面用一段代码来查看Linux操作系统下的进程的运行状态。
1 #include <stdio.h>2 3 int main()4 {5 while(1); 6 return 0;7 }
当运行起来的时候,输入查看进程状态(ps axj | head -1 && ps axj | grep “process”)的指令即可看到。
- 阻塞状态
阻塞状态在Linux操作系统中代表的字母是S。下面用一段代码来查看Linux操作系统下的进程的阻塞状态。
1 #include <stdio.h>2 #include <unistd.h>3 4 int main()5 {6 int cnt = 0;7 while(1)8 {9 printf("value = %d\n",cnt++);10 sleep(1); 11 }12 return 0;13 }
当进程运行的时候,我们观察一下它的进程状态。
原因是代码中有printf函数,该函数是向显示器打印,那么也就是说该进程占用显示器资源。而CPU很快,一下子就可以把命令执行完成,但是显示器相对应CPU,处理速度不快,所以该进程的运行时间里,99%都是阻塞状态,1%是运行状态。所以当我们查看进程状态的时候,大概率是阻塞状态。
- 暂停状态
暂停状态在Linux操作系统中代表的字母是T。下面用一段代码来查看Linux操作系统下的进程的暂停状态。
1 #include <stdio.h>2 3 int main()4 {5 while(1); 6 return 0;7 }
代码运行起来,进程就是运行状态,此时我们输入相关命令,使得进程的状态变为暂停状态。
恢复运行状态:
进程重新恢复运行状态。
- 前台进程与后台进程
#include <stdio.h>2 #include <unistd.h>3 4 int main()5 {6 int cnt = 0;7 while(1)8 {9 printf("value = %d\n",cnt++);10 sleep(1); 11 }12 return 0;13 }
以上面这段代码为例,来看一下前台进程与后台进程。
前台进程:
像这样不能接受命令的进程,称之为前台进程,只能由crtl + c中止。
后台进程:
当像上面正在运行的进程暂停过后,然后又重新启动,此时进程的状态虽然也是运行状态,但是却与上面进程的运行状态有所不同。
- 深度睡眠状态
深度睡眠状态在Linux操作系统中代表的字母是D。下面用一段代码来查看Linux操作系统下的进程的深度睡眠状态。
这个状态不好演示,很容易把系统搞崩。所以直接用语言描述。
假如一个进程A,它的任务就是往磁盘里写入大量数据,但是由于磁盘的读取速度比较慢,那么此时进程A就一直占用着资源。后来,越来越多的进程进入内存,导致内存空间的资源吃紧。于是,操作系统开始排查,发现进程A什么都没在干,而是一直占用资源,于是把进程A干掉了。后来进程A被干掉之后,磁盘读取数据任务完成,出来发现进程A不见了,无法交差,但是手头上的数据也不能一直拿着,所以直接扔了。
后来,用户来查看原来要存放在磁盘的数据,发现数据不见了。于是乎,便盘问了操作系统,进程A,磁盘。磁盘说,我只是个干活的,让我干啥就干啥。进程A说,我也是个干活的,突然间有个家伙要把我干了,我也没办法。操作系统说,我的任务就是维护好资源的分配,所以只能把进程A干掉。
用户觉得谁也没有错,于是制定相关的规定。给予某个重要的进程一个免死金牌,例如进程A,当资源吃紧的时候,操作系统不能杀死带有免死金牌的进程。那么此时,这个带有免死金牌的进程就会进入深度睡眠状态,此时这个进程不能被杀死,只能等进程本身自己醒来或者物理断电解决进程。
一句话总结,处于深度睡眠状态的进程,操作系统是杀不掉的,只能等进程自己醒来或者物理断电。
- 追踪暂停状态
追踪暂停状态在Linux操作系统中代表的字母是t。下面用一段代码来查看Linux操作系统下的进程的追踪暂停状态。
1 #include <stdio.h>2 3 int main()4 {5 printf("hello world\n");6 printf("hello world\n");7 printf("hello world\n");8 printf("hello world\n");9 printf("hello world\n");10 printf("hello world\n");11 printf("hello world\n");12 printf("hello world\n");13 printf("hello world\n");14 printf("hello world\n"); 15 return 0;16 }
当我将这段代码运行起来并调试的时候,就可以清楚地看到这个追踪暂停状态。
3. 僵尸进程
- 僵尸状态
将状态在Linux操作系统中代表的字母是Z。用一个例子,浅浅的认识一下僵尸状态。
一天,小明在路上看到有一个人躺在地上噶了,此时小明选择了报警。警察来了之后,封锁了现场,并且叫来了法医进行验尸。此时,尸体会有一段时间用来被检验,并等待结果,最终宣告死亡。
切换到进程的角度,一个进程退出了,其中资源并不会马上被回收,而是保留一段时间,等待父进程或者操作系统读取。其中这段等待被回收的状态,可以称该进程的状态是僵尸状态。或者可以说该进程没有被父进程或者操作系统回收,也可称该进程是僵尸进程。
如何创建僵尸进程呢?那就是确保父进程正常运行,子进程直接退出。
来看代码:
⮂⮂ buffers 1 #include <stdio.h> 2 #include <unistd.h> 3 #include <stdlib.h> 4 int main() 5 { 6 pid_t id = fork(); 7 if(id == 0) 8 { 9 //child10 printf("i am a child process,process id is :%d,parent id is :%d\n",getpid(),getppid());11 sleep(3);12 exit(1); 13 } 14 else 15 { 16 //parent17 while(1) 18 { 19 printf("i am a parent process,process id is :%d,parent id is :%d\n",getpid(),getppid());20 sleep(1); 21 } 22 } 23 return 0; 24 }
僵尸进程是无法被杀死的,因为它已经退出了,已经退出了的进程是杀不死的。但是它的pcb还存着,等待父进程读取,然后回收。如果父进程不回收,那么就会导致内存泄漏。
4. 孤儿进程
孤儿进程顾名思义就是父进程死了,但是子进程还在跑。这样的进程称为孤儿进程。
下面来看一段代码,看看是如何生成孤儿进程的。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{ pid_t id = fork(); if(id == 0) { //child while(1) { printf("i am a child process,process id is :%d,parent id is :%d\n",getpid(),getppid()); sleep(1); } } else { //parent while(1) { printf("i am a parent process,process id is :%d,parent id is :%d\n",getpid(),getppid()); sleep(1); } } return 0;
}
如果操作系统不领养该进程,该进程退出的时候,变成了僵尸,将会没有人给它收尸。而操作系统作为一个管理角色,必须对其进行处理。
用一句话总结,被领养的进程,我们可以称该进程是孤儿进程。
如果是前台进程创建的子进程,那么该子进程变为孤儿进程后,将会变成后台进程,此时只能用kill命令杀掉该进程。
5. 进程优先级
5.1. 优先级是什么和为什么要有优先级
- 优先级的概念
优先级其实就是排队的先后,优先级在生活中很常见,例如食堂排队打饭,面试工作时懂XX技术优先,这些都是常见的优先级。
- 为什么要有优先级
那么为什么要有优先级呢?是因为资源是有限的,例如饭堂打饭,饭如果打完了,那么优先级低的人就吃不到饭;例如面试时懂XX技术的优先级高,那么有可能优先级低的人就无法获取这份工作…
5.2. Linux中的进程优先级
在Linux中,进程的优先级本质就是PCB上的一个数字。就好比你生活中去一家餐厅吃饭,因为位置不多,所以需要排队,如果你愿意等下去,服务员就会给你一个排队的号码,这个号码就是你的优先级。
下面创建一个进程,并输入相关的指令(ps - la)查看进程优先级。
- 最终进程优先级 = 老的优先级(固定80) + nice值
- 可以用top工具更改进程的优先级,主要是通过更改nice值
注意nice值的范围是[-20,19],所以最小是-20,最大是19。所以进程的最终优先级的范围是[80-20, 80+19]
6. 进程切换
假设你的电脑只有1个CPU,那么就会有很多进程占用CPU的资源。但是当用起来的时候,就感觉进程都是一起运行的。例如你可以同时打开qq,微信,同时在qq和微信上发消息。这是因为操作系统采用进程切换的方法,让多进程在宏观上运行的时候像是一起运行的,实际在微观上是串行的。
具体点就是操作系统会给多个进程分配时间片,当某个进程的时间片用完了,那么该进程就是被操作系统拿下,切换另一个进程运行。这个时间是很短很短的,所以我们一般感觉不出来。
对时间片的概念,可以举这么一个例子:A要考研,他不可能说先把数学学完了再去学英语,然后再去学专业课。一般考研的都是,今天给数学分配多少时间,给英语分配多少时间,给专业课分配多少时间。在这个分配好的时间片里,无论你数学完成的怎么样,我数学的时间片到了,我就得切换到英语科目去学习。最后到考研结束,那么数学也能学完,英语也能学完,专业课也能学完。
把学习数学想象成是一个进程1,学习英语是进程2,学习专业课是进程3,小A是一个CPU,这就可以类比到计算机的进程切换的概念中去。
那么进程的切换是怎么完成的?下面来浅浅地认识一下。
- 先来看一个例子
A是一名大学生,他突然有一天想去服兵役,然后就报名参加了当兵。报名后,A向学校说明了他的情况,学校学籍处给他保留了相应的学籍。当A两年义务兵结束后,选择继续回归校园。此时,退伍回来后,A就向学校学籍处拿回自己的学籍,然后就重新恢复了自己大学生的身份。
切换到计算机的世界。A是一个进程,当A进程去使用打印机资源的时候,那么CPU中的相关的寄存器就会给进程A保留了相关的数据。当进程A完成了打印的任务,回到了原来的轨道。此时,进程A回来后,A就会拿到原来寄存器里的相关数据,继续运行自己的进程。
7. 环境变量
7.1. 环境变量的认识
环境变量其实可以认为是一个字符串,常见的环境变量有PATH,HOME,SHELL…,每个环境变量都是为了应付不同的应用场景的。
- PATH
当我们在命令行输入各种指令的时候,是否有想过为什么直接输入就可以执行相应的操作呢?而当我们写好了一个代码,运行的时候却要在可执行程序的前面指定好路径呢?
其实命令行的指令也是指定好了路径的,这个行为是环境变量帮我们完成的。
如果想要我们自己写的代码也能不加路径直接运行,也有方法。
- 将test拷贝到/usr/bin/
- 配置环境变量
当我们在命令行输入相关的指令,bash进程都会去PATH底下逐一查找,查看这些目录下有没有该命令,如果有则运行,没有则提示找不到。
那么我们只需要把我们代码的路径添加到PATH中,那么运行的时候我们就不用加路径了。
环境变量可以帮助我们在运行相应的指令的时候,让指令识别路径,身份认证等操作。
例如:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{ //获取当前user的环境变量char* name = getenv("USER"); if(strcmp(name,"root") == 0) { printf("%s = %s\n",name,"root"); } else { printf("%s = %s\n",name,name); } return 0;
}
当我是用户1的身份运行时:
当我是root身份运行时:
所以环境变量的用途有很多,它不仅可以帮我们识别路径,也可以帮我们识别用户身份等等…
用背单词的例子来理解环境变量。
7.2. 环境变量相关的命令
- echo命令
操作:显示某个环境变量
示范:
- env
操作:显示所有的环境变量
示范:
- set命令
操作:显示本地变量
示范:
- export命令
操作:设置一个新的环境变量
示范:
- unset命令
操作:清除某个环境变量
示范:
7.3. 环境变量和本地变量
环境变量具有全局性,无论你在哪里用都可以。而本地变量只能当前进程用。
用背单词的例子来认识:
是因为子进程继承了父进程的时候,顺便继承了环境变量,所以才说环境变量具有全局性。
7.4. 命令行参数
C语言中的main函数是可以带有参数的,例如:
int main(int argc, char* argv[])
{return 0;
}
那么带了参数又有什么用呢?
#include <stdio.h>2 #include <string.h>3 #include <stdlib.h>4 int main(int argc, char* argv[])5 {6 for(int i = 0; i < argc; i++)7 {8 printf("argv[%d]--->%s\n",i,argv[i]); 9 }10 return 0;11 }
运行结果:
所以我们之前学习的命令,为什么带上选项可以有不同的功能,就是因为命令行参数的存在。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{ if(argc != 2) { printf("Usage: \n\t%s [-a/-b/-c/-ab/-bc/-ac/-abc]\n", argv[0]); return 1; } if(strcmp("-a", argv[1]) == 0) { printf("功能a\n"); } if(strcmp("-b", argv[1]) == 0) { printf("功能b\n"); } if(strcmp("-c", argv[1]) == 0) { printf("功能c\n"); } if(strcmp("-ab", argv[1]) == 0) { printf("功能ab\n"); } if(strcmp("-bc", argv[1]) == 0) { printf("功能bc\n"); } return 0;
}
运行结果:
可以简单的认为在命令行上执行的程序的程序名,就是argv[0],后面带上的选项就是argv[i]。
7.5. 获取环境变量
- 系统接口getenv()
这里就是简单的系统调用,就不再展示了,上面的有一段代码是写过的。
- char* env[]
main函数中可以有三个参数,其中第三个参数就是环境变量,它同char* argv[] 一样都是一个指针数组,数组的元素都是char类型的,最后一个char是NULL,因此我们可以将它打印出来。
#include <stdio.h>2 #include <string.h>3 #include <stdlib.h>4 int main(int argc, char* argv[], char* env[])5 {6 for(int i = 0; env[i]; i++)7 {8 printf("env[%d]---->%s\n",i,env[i]); 9 }10 return 0;11 }
运行结果:
- extern char* environ
在Linux中,提供一个二级指针,指向了一个保存环境变量的char*[],因此我们只需要在代码中声明该变量,也可以打印出所有的环境变量。
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{ extern char** environ; for(int i = 0; environ[i]; i++) { printf("env[%d]---->%s\n",i,environ[i]); } return 0;
}
运行结果:
7.6. 环境变量学习小总结
- 什么是环境变量?
环境变量简单的来说就是字符串,它可以帮助用户识别路径,识别用户的身份等等操作。
环境变量具有全局性,本地变量具有局部性。具体可以参看背单词的例子。
- 命令行参数
当我们在命令行输入指令的时候,操作系统和shell是怎么认识的?就是通过main函数的参数来识别的。其中我们输入的命令行会被操作系统和shell放到一个char* 数组里面,用来解析我们的各种命令。
- 如何获取环境变量
参考3.5所讲的内容。
相关文章:

【Linux学习笔记】进程概念(中)
1. 操作系统的进程状态2. Linux操作系统的进程状态3. 僵尸进程4. 孤儿进程5. 进程优先级5.1. 优先级是什么和为什么要有优先级5.2. Linux中的进程优先级 6. 进程切换7. 环境变量7.1. 环境变量的认识7.2. 环境变量相关的命令7.3. 环境变量和本地变量7.4. 命令行参数7.5. 获取环境…...

scanpy赋值问题
今天发现一个很奇怪的bug import numpy as np import pandas as pd import anndata as ad from scipy.sparse import csr_matrix print(ad.__version__)counts csr_matrix(np.random.poisson(1, size(100, 2000)), dtypenp.float32) adata1 ad.AnnData(counts) print(adata1)…...

腾讯云域名备案后,如何解析到华为云服务器Linux宝塔面板
一、购买域名并且进行备案和解析,正常情况下,购买完域名,如果找不到去哪备案,可以在腾讯云上搜索“备案”关键词就会出现了,所以这里不做详细介绍,直接进行步骤提示: 二、申请ssl证书࿰…...
odoo 按钮打印pdf报表
odoo打印一般是在动作里面进行的 所以此方法可用自定义按钮进行打印 <template id"report_sale_line_packing_template"> xxx </template><template id"report_sale_line_packing"><t t-call"web.basic_layout"><t …...

用逻辑分析仪观察串口Uart数据波形
一、概述 只讨论嵌入式编程中较为常用的异步串行接口(Universal Asynchronous Receiver/Transmitter, UART),TTL电平。 串口的参数一般有: 1.波特率,数据传输速率,单位bps(bits per…...
数据结构-栈应用括号匹配
1、顺序栈的定义 2、顺序栈的入栈,出栈,取出栈顶元素,匹配判断函数 3、顺序栈的运行测试 4、实现代码 #include<iostream> using namespace std; #define OK 1 #define ERROR 0 #define OVERFLOW -2 typedef int Status; #define M…...
leetcode做题笔记209. 长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。 示例 1: 输入&#…...

【机器学习】几种常用的机器学习调参方法
在机器学习中,模型的性能往往受到模型的超参数、数据的质量、特征选择等因素影响。其中,模型的超参数调整是模型优化中最重要的环节之一。超参数(Hyperparameters)在机器学习算法中需要人为设定,它们不能直接从训练数据…...

使用免费 FlaskAPI 部署 YOLOv8
目标检测和实例分割是计算机视觉中关键的任务,使计算机能够在图像和视频中识别和定位物体。YOLOv8是一种先进的、实时的目标检测系统,因其速度和准确性而备受欢迎。 Flask是一个轻量级的Python Web框架,简化了Web应用程序的开发。通过结合Fla…...

不使用屏幕在树莓派4B安装Ubuntu22.04桌面版(64位)
因为时间有限只说一下基本路径: 1首先安装Ubuntu22.04server版本 2设置服务器版本的SSH和WiFi 3通过服务器版本安装Ubuntu-desktop升级到Ubuntu22.04桌面版 4在桌面版上安装远程控制软件:xrdp; 5使用Windows自带的远程桌面连接访问Ubuntu 6完成...

Pymysql模块使用操作
一、pymysql模块安装 二、测试数据库连接 测试数据库连接.py from pymysql import Connectioncon None try:# 创建数据库连接con Connection(host"localhost",port3306,user"root",password"XXXXX")# 测试链接print(con.get_host_info())print…...

8+双疾病+WGCNA+多机器学习筛选疾病的共同靶点并验证表达
今天给同学们分享一篇双疾病WGCNA多机器学习的生信文章“Shared diagnostic genes and potential mechanism between PCOS and recurrent implantation failure revealed by integrated transcriptomic analysis and machine learning”,这篇文章于2023年5月16日发表…...
springboot如何获取前端请求头的值并加入ThreadLocal
依赖: <dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.7</version> </dependency>示例: public class ThreadLocalUtil {private static ThreadLoc…...

程序员想要网上接单却看花了眼?那这几个平台你可得收藏好了!
现在经济压力这么大,但是生活成本还在上升,相信大家都知道“四脚吞金兽”的威力了吧!话虽如此,但是生活总得继续,为了家庭的和谐幸福,为了孩子的未来,不少人选择多干几份工作,赚点外…...
前端食堂技术周刊第 102 期:Next.js 14、Yarn 4.0、State of HTML、SEO 从 0 到 1
美味值:🌟🌟🌟🌟🌟 口味:肥牛宽粉 食堂技术周刊仓库地址:https://github.com/Geekhyt/weekly 大家好,我是童欧巴。欢迎来到前端食堂技术周刊,我们先来看下…...

GPT与人类共生:解析AI助手的兴起
随着GPT模型的崭新应用,如百度的1和CSDN的2,以及AI助手的普及,人们开始讨论AI对就业市场和互联网公司的潜在影响。本文将探讨GPT和AI助手的共生关系,以及我们如何使用它们,以及使用的平台和动机。 GPT和AI助手…...

HTML脚本、字符实体、URL
HTML脚本: JavaScript 使 HTML 页面具有更强的动态和交互性。 <script> 标签用于定义客户端脚本,比如 JavaScript。<script> 元素既可包含脚本语句,也可通过 src 属性指向外部脚本文件。 JavaScript 最常用于图片操作、表单验…...
UOS安装Jenkins
一,环境准备 1.安装jdk 直接使用命令行(sudo apt install -y openjdk-11-jdk)安装jdk11 2.安装maven 参考此篇文章即可 UOS安装并配置Maven工具_uos 安装maven_蓝天下的一员的博客-CSDN博客 不过要注意这篇文章有个小错误,我…...
纯CSS实现卡片上绘制透明圆孔
<template><div class"dot-card-wrapper"><div class"top-wrapper"><slot name"top"></slot></div><!-->核心是下面这部分</--><div class"dot-row"><div class"left-…...

用前端框架Bootstrap的AdminLTE模板和Django实现后台首页的页面
承接博文 用前端框架Bootstrap和Django实现用户注册页面 继续开发实现 后台首页的页面。 01-下载 AdminLTE-3.1.0-rc 并解压缩 以下需要的四个文件夹及里面的文件百度网盘下载链接: https://pan.baidu.com/s/1QYpjOfSBJPmjmVuFZdSgFQ?pwdo9ta 下载 AdminLTE-3.1…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...

【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...

消息队列系统设计与实践全解析
文章目录 🚀 消息队列系统设计与实践全解析🔍 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡💡 权衡决策框架 1.3 运维复杂度评估🔧 运维成本降低策略 🏗️ 二、典型架构设计2.1 分布式事务最终一致…...

五子棋测试用例
一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏,有着深厚的文化底蕴。通过将五子棋制作成网页游戏,可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家,都可以通过网页五子棋感受到东方棋类…...
[USACO23FEB] Bakery S
题目描述 Bessie 开了一家面包店! 在她的面包店里,Bessie 有一个烤箱,可以在 t C t_C tC 的时间内生产一块饼干或在 t M t_M tM 单位时间内生产一块松糕。 ( 1 ≤ t C , t M ≤ 10 9 ) (1 \le t_C,t_M \le 10^9) (1≤tC,tM≤109)。由于空间…...