Linux进程 (冯诺依曼体结构 管理 PCB 进程状态 僵尸进程 孤儿进程 运行阻塞挂起状态 进程优先级)
文章目录
- 一.冯·诺依曼体系结构
- 冯诺依曼结构能干什么?
- 二.操作系统
- 概念
- 结构图(不完整)
- 为什么要有操作系统?
- 尝试理解操作系统
- 管理
- 结构图(完整)
- 总结:
- 三.进程
- 进程是什么?
- PCB
- 为什么要有PCB?
- Linux中的PCB
- 进程的task_struct本身内部的属性有哪些?
- 终止进程
- 进程创建的代码方式(fork函数)---重操作,轻原理
- 我们为什么要创建子进程?
- 多进程
- task_struct的内容
- 查看进程(通过/proc查找)
- 四.进程状态
- R状态 S状态
- 状态+中的+是什么意思?
- T状态 t状态
- D 状态
- Z 状态(僵尸进程) 与X 状态
- 孤儿进程
- 纯理论:进程的阻塞和挂起,运行
- 运行状态
- 阻塞状态
- 挂起状态
- 进程切换
- 进程优先级
- 什么是优先级?
- 为什么要有优先级?
- 如何查看优先级呢?
- top更改进程优先级
- nice与renice
一.冯·诺依曼体系结构
那么问题就来了,为什么要加一个储存器
直接输入设备–>CPU–>输出设备不好吗?
短板在输入设备和输出设备,所以加了个存储器
在计算机里面,离CPU越近,效率越高,造价越贵
存储金字塔
总结:硬件流动角度,数据层面中:(蓝色箭头)
1.CPU不和外设直接打交道,CPU之和内存打交道
2.外设(输入和输出)的数据,不是直接给CPU的,而是先要放入内存中的
冯诺依曼结构能干什么?
引例:“你给你的朋友用QQ发送你好!!”的过程
二.操作系统
概念
开机的操作就是启动操作系统
操作系统是一款软硬件资源管理的软件(比如插个U盘,电脑会显示,可以往U盘里写东西)
操作系统广义的认识:操作系统内核+操作系统的外壳周边程序
狭义:只是操作系统的内核
windows也可以没有图形化界面的
安卓的操作系统属于两层
结构图(不完整)
体系结构的层状划分结构如下
因为操作系统需要硬件的数据,那么每次更新硬件,操作系统获得数据的方式可能跟上一个配对的硬件的方式不一样,那么操作系统就得跟着更新,才能与硬件配对,获取数据
所以操作系统不直接找硬件要相关数据,而是通过驱动层,这样只需要更新驱动就行。(驱动层是独立的,操作系统是核心,更新驱动层肯定比直接更新操作系统方便、安全)
就比如鼠标,在插入电脑的时候,不能直接使用,是因为驱动层还没有下好。右下角会弹窗显示插入或者鼠标亮了(现在插进去响一声),才能使用。
为什么要有操作系统?
举个例子:
学校有椅子、桌子、粉笔、图书馆里的书、体育器材
角色有老师、保安、校长、教导主任、医生
图书馆里的书需要图书馆管理员管理,椅子桌子坏了找谁报修,学生生病找谁
有了角色的担任,管理起来就会变得方便
操作系统就是对软硬件进行管理
为用户提供提供一个良好(稳定的、安全的、高效的)运行环境
良好的反例是指:用电脑玩原神,10分钟一黑屏,5分钟一重启,就是因为某个硬件造成的。
尝试理解操作系统
管理
管理在生活中无非在做两件事:1.决策 2.执行
比如说不想上今天的早8,这就决策。今天去早8了,这叫执行
在学校层面:校长为管理者,学生是被管理者
随着被管理的学生的增多,同学的信息也变得非常多,校长很难管理
但是校长会C语言,写了一个关于学生属性的表
张三的属性就可以用结构体表达出来
学生有很多人,校长要在5W个学生中找到张三同学,为了节省时间,校长就加了给指针,形成了链表
校长对学生的管理工作(日常),变成了对链表的增删查改(计算机语言)
于是校长完成了对计算机的建模工作,也就是对学生的管理工作
校长想开除张三,就变成了删除张三的节点
综上所述,管理学生:先把学生的信息描述起来,然后再组织
结论:任何管理:先描述,再组织
引例:C++先提供描述的能力,STL标准库,有各种容器,提供组织的能力
那么如何管理硬件呢?
比如插入鼠标的一瞬间,进程管理会创建一个关于鼠标的结构体,把鼠标的驱动程序读取到的数据写入该进程(先描述),并以算法(链表等)的形式插入前面的节点后面。(再组织)
不仅仅是进程管理是这样,只要是与管理相关的都大差不差
结构图(完整)
谈谈在操作系统上层的部分
作为用户能否直接访问底层硬件吗?
故事:
隔壁的校长是接触不到张三的,万一张三被拐走了,辅导员找不到人了就是管理人员的失职。要找也是找张三的校长
所以任何访问硬件的操作,都得通过操作系统来做
我们(用户)用C语言中的fopen fclose就经过文件管理,再写进磁盘,绕不过操作系统
同理printf是从显示器上读取数据,scanf是从键盘上读取数据,也是绕不开操作系统的
那用户能否直接访问操作系统呢?
故事:
又比如:现在的你改一改操作系统,然后打起了原神,就因为改了操作系统直接蹦掉了。所以用户是不能直接接触操作系统的
上面的故事映射到计算机里面就是:银行中的柜台就是系统调用接口
这样就可以受管控的使用操作系统
故事进入第二阶段:
作为新时代的青年,准备材料去存钱开户什么的都知道。
但是有一天,来了一个老奶奶要存1000万,但是不会操作
银行经理就是外壳程序,帮助用户开发等操作
开发的时候,直接使用系统调用接口,是不具有跨平台性的,在Linux上能跑,windows可不一定能跑
例子:
总结:
三.进程
操作系统中,进程可以同时存在非常多
如何管理这么多进程呢?
先描述,再组织
进程是什么?
假设我们要运行一个名为a.out的可执行文件(程序 = 代码 + 数据)
根据冯诺依曼结构,任何可执行程序都需要进入内存,交给CPU处理
问题来了,下面图中的内存是进程吗?
可以这样想:如果文件很多,哪个先运行,哪个后运行,什么时候到我运行,堆和栈在哪?
所以:
操作系统想要管理进程:就得先描述,再组织。
PCB
PCB全称process control block
PCB在哪里?
在操作系统里,我们电脑或手机开机就是加载操作系统(操作系统也是软件)
注意的是:操作系统是对PCB的管理,而非对可执行程序管理
为什么要有PCB?
OS要进行管理,就得先描述,在组织
Linux中的PCB
通常进程排队指的是PCB(struct task_struct)排队,而不是数据
因为队列的首部的节点是a.out
所以CPU会把a.out的数据弄到CPU中去运行
总结:调度运行进程,本质就是让进程控制task_struct进行排队
举个通俗点的例子:
同学投简历,大厂会筛选简历,就是对简历(进程)的增删查改,就是对同学(数据)的管理
所以在Linux中进程的概念:进程 = 内核task_struct 结构体 + 程序的代码和数据
进程的task_struct本身内部的属性有哪些?
例子:
Makefile文件
myprocess:myprocess.cgcc -o $@ $^
.PHONY:clean
clean:rm -f myprocess
myprocess.c文件
#include <stdio.h>
#include <unistd.h>int main()
{while(1){printf("I am a process!\n");sleep(1);}return 0;
}
如何查看当前的进程呢?
ps axj
ps:查看当前的进程
a:是all的意思
xj:是显示进程的详细信息
axj的顺序可以乱
一个可执行文件和其进程的名字默认是一样的
查看myprocess文件的进程的命令:
ps axj | grep myprocess
会发现有两个关于myprocess的进程,是因为grep本身的进程也被查到了
显示的每一个信息是什么呢?
显示进程的第一行
ps axj | head -1
结合起来:
一个进程,如何知道自己的pid?
前面讲了,用户无法直接访问操作系统
就需要系统调用接口getpid
myprocess.c的代码
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main()
{pid_t id = getpid();while(1){printf("I am a process!,pid:%d\n",id);sleep(1);}return 0;
}
发现进程中的pid与运行起来的pid一样
终止进程
ctrl + C 就是在用户层面终止进程
kill -9 pid
可以直接杀掉进程
进程创建的代码方式(fork函数)—重操作,轻原理
发现还有一个getppid,第一个p是parent,第二个p是process,意思是获得当前进程的父进程的id
看一下父进程id是什么
myprocess.c的代码:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main()
{pid_t id = getpid();pid_t parent = getppid();while(1){printf("I am a process!,pid:%d,ppid:%d\n",id,parent);sleep(1);}return 0;
}
跑起来会发现
其中18839是什么?
是bash
bash是父进程,是命令行解释器,在Linux权限篇中讲了bash是媒婆,派实习生(子进程)的的故事
创造子进程,因为用户是不能直接去触碰操作系统的,所以用系统调用接口fork。
myprocess.c的代码如下
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main()
{printf("process is running,only me!\n");sleep(3);fork(); printf("hello world\n");sleep(5);return 0;
}
运行上面的可执行程序时,运行下面的指令,方便观察进程。-v 是去掉grep的进程
while :; do ps ajx | head -1 && ps ajx | grep myprocess | grep -v grep;sleep 1;done
运行结果:
可以发现
我们为什么要创建子进程?
想让子进程和父进程执行不一样的代码
fork会返回两个值
成功后,子进程的 PID 将在父进程中返回,在子进程中返回 0。 失败时,父进程中返回 -1,不创建子进程。
验证一下fork
process的代码如下:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main()
{printf("process is running,only me!\n");sleep(3);pid_t id = fork();if(id == -1) //失败{return 0;}else if(id == 0) //子进程{while(1){printf("id:%d,I am child process,pid:%d,ppid:%d\n",id,getpid(),getppid());sleep(1);}}else //父进程{while(1){printf("id:%d,I am parent process,pid:%d,ppid:%d\n",id,getpid(),getppid());sleep(2);}}return 0;
}
会发现确实有两个返回值,并且子进程的pid将在父进程中返回
于是就出现了两个问题:
1.同一个id,怎么可能即是 == 0,又是 > 0?
2.fork为什么会有两个返回值,并且返回两次
父进程的代码从磁盘中带出来的,子进程只能copy父进程给的代码。
数据上有些独特
解答一下第二个问题
多进程
代码如下:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>void RunChild()
{while(1){sleep(1);printf("I am child process,pid:%d,ppid:%d\n",getpid(),getppid());}
}int main()
{int i = 0;const int num = 5; //创建5个子进程for(i = 0;i<num;i++){pid_t id = fork();if(id == 0) //子进程进入{RunChild();}sleep(1); //父进程继续往下走}while(1){sleep(1);printf("I am parent process,pid:%d,ppid:%d\n",getpid(),getppid());}return 0;
}
可以看到进程逐渐变多
task_struct的内容
标识符:ppid pid 用来和别的进程做区分
状态:任务状态、退出代码、退出信号等
优先级:想对于其它进程的优先级
程序计数器: 程序中即将被执行的下一条指令的地址
内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]
I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等
其他信息
查看进程(通过/proc查找)
进程的信息也可以通过 /proc
系统文件夹查看
假设要获取进程的PID==1的程序
直接查看/proc/1
文件就行
举个例子:
进入proc文件,会发现文件里面的目录都是进程,目录名称就是PID
其中,/proc/PID
目录中值得注意的是这两个
第一个表示的是:进程的当前工作路径
第二个表示的是:进程的PCB中会记录自己对应的可执行程序的路径
把这个进程干掉,发现程序还在跑。(这个图片显示不出来,得自己实验)
因为把磁盘中的文件删掉了,但是进程的代码与数据已经在内存里了
然后发现cwd和exe没了
每个进程在启动的时候,会记录自己当前在哪个路径下启动
验证:下面是个简单的文件函数
#include <stdio.h> int main()
{FILE* fp = fopen("log.txt","w");(void)fp;//ignore warningreturn 0;
}
因为是在该目录下运行的进程(a.out),所以默认在该目录下创建log.txt文件
更改进程的所在路径
用到的函数时chdir
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main()
{chdir("/home/sjl");//更改的路径FILE* fp = fopen("log.txt","w");(void)fp;//ignore waringfclose(fp);while(1)//显示出进程在运行{printf("I am a process,pid:%d\n",getpid());sleep(1);}return 0;
}
进程的路径被更改
会发现在更改的路径下创建log.txt,而运行可执行程序的路径下时没有的
所以一旦把当前进程的工作目录改了,那么新建对应的一个文件,他就在改过进程的当前目录下
四.进程状态
大概就是下面这种形式
下面的状态在kernel源代码里定义:
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 */
};
R状态 S状态
引例:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main()
{while(1){printf("I am a process,pid:%d\n",getpid());}return 0;
}
运行的时候老样子,用以下指令查看进程(可执行程序为a.out)
while :; do ps ajx | head -1 && ps ajx | grep a.out | grep -v grep;sleep 1;done
会发现是S+的状态,是sleep,休眠状态
然后把printf注释掉
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main()
{while(1){//printf("I am a process,pid:%d\n",getpid());}return 0;
}
再次运行代码,会发现是R+状态,R为进程运行状态
原因:打印的时候,是往屏幕上打印的,屏幕是外设,CPU运行比外设快很多,CPU需要等显示屏的资源就绪。所以CPU大部分处于S状态,运气好的时候遇到CPU正在执行printf就能查到在R状态
S(休眠状态)本质分为两种:
第一种:进程在等待“资源”就绪(就是上面的例子)
第二种:可中断睡眠(进程处于睡眠的状态(比如sleep函数),但依旧可以被ctrl + c中断)
状态+中的+是什么意思?
代表的是在前台运行还是后台运行
在进程后面加个&代表在后台运行
运行后你就会发现ctrl + c中止不了
用kill -9 PID终止进程
T状态 t状态
显示出Linux的信号的指令:-l是list
kill -l
其中9号信号是不是很眼熟,杀掉进程
上面的信号底层就是宏,跟C语言中的INT_MAX意义差不多
其中19号信号SIGSTOP就是暂停进程
验证:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main()
{while(1){sleep(1);printf("I am a process,pid:%d\n",getpid());}return 0;
}
S状态直接变为T状态
T状态:让进程暂停,等待被进一步唤醒(进程被暂停了,自动变为后台)
18号信号SIGCONT,continue的意思,让进程继续
调试就是进程暂停
遇到断点处,进程就暂停了
D 状态
D:Linux系统比较特有的一种状态(disk是磁盘)
因为配置的原因很难演示出来,所以拿图来讲解:
进程要往磁盘中存1个GB的数据
内存严重不足,操作系统马上被毙掉了,然后看见这个进程悠然自得的SLEEP,一怒之下,把他删了。磁盘找不到了,造成了数据的丢失
这不行啊,好比说内存是银行的系统,被删掉的进程是银行的转账记录,直接被干没了,造成了上百万的损失。
为了防止这类事情的发生,规定凡是进程要进行数据IO等待外设的时候,进程要将自己的状态设成D状态
D状态:不可被杀,被称为深度睡眠,也被称为不可中断睡眠(S就是浅度睡眠,可被杀和中断)
要唤醒D状态有两种方法:
1.进程自己醒来
2.重启,重启不行就断电
Z 状态(僵尸进程) 与X 状态
一个进程退出的时候,他会把自己退出的信息保留在PCB当中,如果没有人读取PCB中退出进程的消息,这个进程就一直不释放,一般会把代码和数据释放掉,但PCB内容与数据结构会一直存在,直到将来对该进程进行等待,如果不等待就一直处于僵尸状态。如果等待了就会转化为X状态,进而将进程所有的资源全部释放掉
引例:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main()
{pid_t id = fork();if(id == 0){//childint cnt = 5;while(cnt)//子进程运行5次后退出{printf("I am child,cnt:%d,pid:%d\n",cnt,getpid());sleep(1);cnt--;}}else {//parentwhile(1)//父进程一直不退出{printf("I am a parent,running always!pid:%d\n",getpid());sleep(1);}}return 0;
}
子进程运行结束后就是Z状态(僵尸状态)
子进程运行完毕,但需要维持自己的退出信息,在自己的进程task_struct会记录自己的退出信息,未来让父进程来读取
因为X状态释放是一瞬间的,所以查不出来
平时子进程创建出来是要完成任务的,得知道完成任务怎么样(获取子进程退出的信息)
kill不掉僵尸进程的,已经死进程了,杀不了了。
孤儿进程
如果父进程先退出了,那么子进程就是孤儿进程
就是与僵尸进程相反,所以验证的代码也相反:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main()
{pid_t id = fork();if(id == 0){//childwhile(1){printf("I am child,pid:%d\n",getpid());sleep(1);}}else {int cnt = 5;//parentwhile(cnt){printf("I am a parent,cnt:%d,pid:%d\n",cnt,getpid());sleep(1);cnt--;}}return 0;
}
发现两个S的进程就剩1个S的进程,剩下的那个S进程就是孤儿进程
问题就来了:父进程都没了,谁去回收孤儿进程?
答:孤儿进程一般都会被1号进程(OS本身)进行领养的
孤儿进程为什么要被OS领养?
答:依旧要保证子进程正常被回收
孤儿进程是可以被kill的
以前我们启动的所有进程(运行C语言代码)。怎么从来没有关心国】过僵尸进程呢?内存泄漏?
答:直接在命令行中启动的进程,他的父进程是bash,bash会自动回收新进程的Z
父进程的一般核心工作都是回收子进程
纯理论:进程的阻塞和挂起,运行
大多数书上的进程状态
运行状态
进程在运行队列中,该进程的状态就是R状态。
R状态不是指直接在CPU上去运行,而是值我已经准备好了,可以随时被调度了
一个进程一旦持有CPU,会一直运行到这个进程结束吗?
不会,就比如里面写个死循环,CPU调度就不会走了,其他进程被卡死了。
现实就是打着原神,微信还能收到信息。
是因为当代的内核基于时间片轮转调度的。
假设时间片设置的2毫秒,2毫秒一到,当前进程就会在CPU上剥离下来,插到队列的尾部,然后下一个进程上前,进入CPU
这样就可以让多个进程以切换的方式进行调度,在一个时间段内同时得以推进代码。就叫做并发
Linux不是这样调度的,上面方法太简单了。只是调度算法的一种。
如果存在两个CPU,就有两个调度队列
根据不同的进程,放到不同队列,也可以放进两个队列
任何时刻,都同时有多个进程在同时运行,我们叫做并行
阻塞状态
问题:我们在写C语言的时候,用过一个接口scanf,如果我们不输入的话,进程处于什么状态?另外scanf在等待什么资源呢?
测试代码如下:
#include <stdio.h>int main()
{int a = 0;scanf("%d",&a);printf("a = %d\n",a);return 0;
}
会发现是S状态,其实D也算阻塞状态,不过无法演示
他在等什么呢?在等键盘资源是否就绪,键盘上面有没有被用户按下的按键,按键数据交给进程
键盘上面没数据,进程是不OK,该进程并没有被运行的(R状态),所以一定不在运行队列中
操作系统要对所有的硬件做管理,那么操作系统如何对硬件做管理?
管理肯定离不开先描述,在组织
一个进程如何等待一个设备呢?
不只是CPU才有等待队列,设备中也有等待队列wait_queue
演示一下scanf等待键盘资源的总过程:
总结:阻塞和运行状态的变化,往往伴随着PCB被连入到不同的队列中
入队列的不是进程的代码和数据,而是进程的task_struct
挂起状态
我们在装系统的时候,会有一个swap分区,大多数情况swap分区是内存的1.5倍2倍,可以自己定义。
当OS中内存吃紧,且有进程处于阻塞状态(暂时不会被调度),那么就把该进程的代码和数据唤出到swap分区中。这样内存就会腾出空间
这种状态叫做阻塞挂起态
如果该设备又等待就绪了,就会把进程的代码和数据唤入到内存
这样可以更合理的使用内存资源
还有很多挂起,就绪挂起等。本质都是一样的。
频繁的唤入唤出会导致效率问题。牺牲效率换取空间
不建议把swap分区放大太,因为操作系统会过渡依赖swap分区,一压力大就唤出。要逼着操作系统合理的分配内存
swap分区的位置
ls /proc/swaps
进程切换
CPU内部的所有寄存器中的临时数据,叫做进程的上下文
寄存器本身是硬件,具有数据的存储能力,CPU的寄存器硬件只有一套
但CPU内部的数据可以有多套,有几个进程,就有几套和该进程对应的上下文数据
进程优先级
什么是优先级?
指定进程获取某种资源(比如CPU)的先后顺序
进程控制模块task_struct中的内部字段有一个或多个整型(比如int prio =)的优先级数字
Linux中优先级数字越小,优先级越高
为什么要有优先级?
进程访问的资源(CPU)是有限的
进程比硬件资源多,显示屏就一个,网页有很多
操作系统关于调度和优先级的原则:分时操作系统,保证了基本公平
如果进程因长时间不被调度,就造成了饥饿问题(比如学生打饭,教导主任差一下队,校长插一下队)
如何查看优先级呢?
引例:
#include <stdio.h>
#include <unistd.h>int main()
{while(1){printf("I am a process,pid:%d\n",getpid());sleep(1);}return 0;
}
查看当前终端的进程
ps -l
想查看全部终端的进程
ps -al
PRI:进程优先级
NI:进程优先级的修正数据(nice值),新的优先级 = 优先级 + nice
top更改进程优先级
top
先输入top
然后输入r
输入需要调整优先级的PID
输入100,然后按回车
会发现优先级是99,不是80+100
这是因为nice并不能任意调整,是有范围的(-20~19)
如果能随便调,把优先级调很高,就可能会一直运行一个进程,影响了调度的平衡
第二次改的时候不让改了,因为一个进程的优先级是不能频繁改的
这里切root用户更改,nice的值为6
发现不是99+6,而是80+6
因为每次调整优先级,都是从80开始的
nice与renice
这两也可以更改优先级
nice命令格式:nice -n [NI值] [命令]
加不加n都行
renice命令格式:renice [NI值] [PID]
相关文章:
Linux进程 (冯诺依曼体结构 管理 PCB 进程状态 僵尸进程 孤儿进程 运行阻塞挂起状态 进程优先级)
文章目录 一.冯诺依曼体系结构冯诺依曼结构能干什么? 二.操作系统概念结构图(不完整)为什么要有操作系统? 尝试理解操作系统管理结构图(完整)总结: 三.进程进程是什么?PCB为什么要有PCB? Linux中的PCB进程的task_struc…...
《LlamaIndex 之美》-01-LLM、Prompt、Embedding基础入门
在基于数据构建任何 LLM 应用程序时,选择合适的大型语言模型 (LLM) 是您需要考虑的首要步骤之一。 LLM 是 LlamaIndex 的核心组成部分。它们可以作为独立模块使用,也可以插入到其他核心 LlamaIndex 模块(索引、检索器…...
C++ 智能指针简单介绍及用法
C 智能指针简单介绍及用法 智能指针是 C11 引入的一个非常实用的特性,旨在自动管理动态分配的内存,避免内存泄漏和悬空指针问题。主要有三种类型的智能指针:std::unique_ptr、std::shared_ptr 和 std::weak_ptr。下面是对它们的详细介绍&…...
k8s笔记之创建Istio Gateway规则
创建Istio Gateway 背景如何创建Istio Gateway规则配置方式rewrite重写路径直接去除match,默认都转发到一个服务路由规则多种配置方式实践(即开头的完整版) 涉及的命令补充注意事项 背景 为什么需要使用到Istio Gateway?充当k8s服…...
NAND行业回归盈利:AI与云存储需求驱动
市场概览 根据Yole Group于2024年6月25日发布的市场报告,经过五个季度的亏损之后,NAND闪存行业在2024年第一季度(1Q24)实现了盈利回归。这一转变主要得益于企业级固态硬盘(SSD)领域的强劲需求增长…...
【限免】频控阵雷达:概念、原理与应用【附MATLAB代码】
微信公众号:EW Frontier QQ交流群:949444104 主要内容 PDA、FDA MATLAB代码 %---------------------------------------- %功能:FDA和相控阵天线方向图 %版本:ver1.0 %时间:2017.11.1 %--------------------------------------- clear all; clc; disp…...
从0开始搭建vue + flask 旅游景点数据分析系统( 六):搭建后端flask框架
这一期开始开发header部分,预期实现两个目标: 创建 Flask 项目导入旅游数据后端实现旅游数据的查询 1 python 环境 & 开发环境 python 安装和pycharm安装需要去网上找包,建议python使用3.8 或者3.9版本 2 新建项目 我们新建一个文件…...
学习硬件测试04:触摸按键+PWM 驱动蜂鸣器+数码管(P62~P67、P71、P72)
一、触摸按键 1.1理论讲解 1.1.1实验现象 触摸按键 1 单击与长按,控制 LED1;触摸按键 2 单击与长按,控制 LED2;触摸按键 3 单击与长按,控制 LED3;触摸按键 4 单击与长按,控制继电器; 1.1.2硬件电路 是原理图上触摸…...
JS原型链
JS的原型链 文章目录 JS的原型链前言一、原型是什么?二、原型链总结 前言 在使用数组或对象中的方法时,你是不是会感觉很奇怪,为什么仅仅是创建了一个数组或是对象,就能够使用它提供的方法呢?JS是怎么做到的呢&#x…...
《Java初阶数据结构》----5.<二叉树的概念及使用>
前言 大家好,我目前在学习java。之前也学了一段时间,但是没有发布博客。时间过的真的很快。我会利用好这个暑假,来复习之前学过的内容,并整理好之前写过的博客进行发布。如果博客中有错误或者没有读懂的地方。热烈欢迎大家在评论区…...
git查看记录详解
文章目录 git查看记录查看文件修改列表查看修改差异友好的查看修改记录结合多个选项查看记录示例输出 git查看记录 使用 git log 你不仅可以查看提交记录,还可以通过一些选项查看文件的修改列表、修改差异,并以更友好的方式查看修改记录。以下是一些常用…...
检索增强生成RAG系列10--RAG的实际案例
讲了很多理论,最后来一篇实践作为结尾。本次案例根据阿里云的博金大模型挑战赛的题目以及数据集做一次实践。 完整代码地址:https://github.com/forever1986/finrag.git 本次实践代码有参考:https://github.com/Tongyi-EconML/FinQwen/ 目录 …...
程序员自我提升的全面指南
程序员自我提升的全面指南 1. 技术基础巩固重要性实践方法 2. 技术栈拓展重要性实践方法 3. 软技能提升重要性实践方法 4. 实践与项目经验重要性实践方法 5. 持续学习与职业规划重要性实践方法 6. 代码质量与优化重要性实践方法 7. 思维与创新能力重要性实践方法 8. 健康与心理…...
【golang】Golang手写元组 tuple | golang tuple
Golang手写元组 tuple 1、源码 如下: package tupletype Tuple[T any, U any] struct {First TSecond U }// zip combines elements of two slices into a slice of pairs (tuples), which is useful for combining related data. func Zip[T any, U any](slice…...
golang中struct的tag -简记
今天 简单整理一下,关于golang中struct的tag type User struct {UId int gorm:"column:uid;type:bigint;unique_index;not null;comment:用户id"Name string json:"name"Age int bson:"age"From string binding:"requi…...
分布式领域扩展点设计稿
分布式领域扩展点设计稿 背景坐标设计理念设计图Quick Start相关组件 背景 随着交易业务和基础知识的沉淀,愈发觉得扩展点可以在大型交易分布式架构中可以做更多的事情。 经过一个月的思考,决定将 单点领域扩展点(savior-ext) 从…...
玩转微信公众号变现:从新手到专家的全攻略
个人名片 🎓作者简介:java领域优质创作者 🌐个人主页:码农阿豪 📞工作室:新空间代码工作室(提供各种软件服务) 💌个人邮箱:[2435024119qq.com] 📱…...
JVM: 方法调用
文章目录 一、介绍二、方法调用的原理1、静态绑定2、动态绑定(1)介绍(2)原理 一、介绍 在JVM中,一共有五个字节码指令可以执行方法调用: invokestatic: 调用静态方法。invokespecial:调用对象…...
测试面试宝典(四十一)—— 接口自动化的优缺点
接口自动化测试的优点: 1. 提高测试效率:能够快速执行大量的测试用例,节省了手动测试重复执行的时间和人力成本。 2. 尽早发现问题:可以在软件开发的早期阶段介入,有助于及时发现接口层面的缺陷,降低修复…...
“火炬科企对接”先进计算产业推进会 | 麒麟信安受邀参加,并签署开源生态合作协议
7月30日,“火炬科企对接”先进计算产业推进会在长沙隆重召开。大会由工业和信息化部火炬高技术产业开发中心、湖南省科学技术厅、湖南省工业和信息化厅、湖南湘江新区管理委员会、中国邮政储蓄银行联合举办。麒麟信安与来自国内先进计算领域的专家学者,2…...
中文网址导航模版HaoWa1.3.1/模版网站wordpress导航主题
HaoWa v1.3.1由挖主题开发的一款网址导航类主题。 HaoWA主题除主体导航列表外,对主题所需的小模块都进行了开放式的HTML编辑器形式的功能配置,同时预留出默认的代码结构,方便大家在现有的代码结构上进行功能调整。 同时加入了字体图标Font …...
图欧学习资源网创站以来的更新日志(截止至2022.5.6)不完全统计
一、网站创立和初步发展 2021年10月28日创建【TUO图欧视频备份站】,当时只有【单词视频】文件夹. 小学、初中、高中、大学、四六级、专四、专八、专升本、考研、考博、托福、雅思、托业、GRE、SAT、GMAT、MBA、新概念等 数量:500个文件,60个…...
现代前端架构介绍(第二部分):如何将功能架构分为三层
远离JavaScript疲劳和框架大战,了解真正重要的东西 在这个系列的前一部分 《App是如何由不同的构建块构成的》中,我们揭示了现代Web应用是由不同的构建块组成的,每个构建块都承担着特定的角色,如核心、功能等。在这篇文章中&#…...
LeetCode Easy|【21. 合并两个有序链表】
力扣题目链接 状态:拿到本题的第一反应就是使用双指针,分别指向两个链表的开头位置。 随后的思路就是以第一条链表为基准完成插入,并且对于遍历到的每个节点都应该保存其状态。 写了一下代码后发现,我们应该以第一个节点较小的链表…...
大模型的架构参数是指定义模型基本结构和组成的各种参数,这些参数对模型的性能、训练效率和泛化能力具有重要影响。以下是对大模型架构参数的详细介绍
大模型架构参数 大模型的架构参数是指定义模型基本结构和组成的各种参数,这些参数对模型的性能、训练效率和泛化能力具有重要影响。以下是对大模型架构参数的详细介绍: 一、基本结构和组成 层数:模型的层数是指模型中全连接网络或特定结构…...
人工智能会越来越闭源——对话东北大学副教授王言治 | Open AGI Forum
作者 | Annie Xu 责编、采访 | Echo Tang 出品丨GOSIM 开源创新汇 在读期间研究方向为并不“火”的模式识别与深度学习,毕业却刚好踩上人工智能计算研究的风口……来自美国东北大学的王言治副教授深耕深度学习与大模型,前瞻性地探索大模型的本地化部署…...
【前端】(仅思路)如何在前端实现一个fc手柄,将手机作为游戏手柄设备。
文章目录 背景界面demo原型图(没错,就是它,童年回忆) 遇到的问题最终后端demo(甚至比前端逻辑更简单) 背景 突发奇想,想要在前端实现一个fc游戏手柄,然后控制电脑的nes模拟器玩玩魂斗罗。 思路很简单&…...
三十种未授权访问漏洞合集
未授权访问漏洞介绍 未授权访问可以理解为需要安全配置或权限认证的地址、授权页面存在缺陷,导致其他用户可以直接访问,从而引发重要权限可被操作、数据库、网站目录等敏感信息泄露。---->目录遍历 目前主要存在未授权访问漏洞的有:NFS服务&a…...
【Golang 面试 - 进阶题】每日 3 题(十五)
✍个人博客:Pandaconda-CSDN博客 📣专栏地址:http://t.csdnimg.cn/UWz06 📚专栏简介:在这个专栏中,我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话,欢迎点赞👍收藏…...
Java中实现文件上传
目录 1、文件上传本地 1.1 原理 1.2 如何使用文件上传 1.2.1 引入文件上传的依赖 1.2.2 配置文件上传拦截器 1.2.3 完成文件上传的代码 2、文件上传oss服务器 2.1 为什么需要上传到oss服务器 2.2 如何使用oss 2.2.1 开启oss服务 2.2.2 在Java中引入依赖 2.2.3 查看自…...
dw个人网站主页怎么做/网站查询平台官网
springmvc hibernate easyui 整合 demo前台easyui 后台hibernate springmvc框架。 demo主要设计功能点还有 spring注解事物控制。pushlet、p6spy、日志监控、时间戳功能数据库mysql :demo只用一张表做了一个测试表 表结构如下:CREATE TABLE user (Id int(11) NOT NULL auto…...
怎么制作图片视频/苏州seo
一、前面已经介绍了初始化列表的好处,尤其对于类类型的变量来说,会提高效率,下面来介绍必须放在初始化列表的情况(无关效率问题): 1、常量成员,因为常量(const)只能初始化…...
免费做团购网站的软件好/杭州seo代理公司
现在越来越多的人学习Java,但是却只有很少的人能将Java学有所成,很多人都只是为了一份差不多的工作,学习的也只是一些皮毛。但其实这种人只能称为码农,距离工程师还有一段距离,距离大牛就更是远的不着边了。那么如果你…...
做网站实名认证总是失败怎么回事/全球搜索引擎大全
源码获取:俺的博客首页 "资源" 里下载! 项目介绍 网上花店销售系统采用JSPServletJavaBean的MVC模式,将数据对象、业务逻辑以及用户界面分离。该系统分为用户和管理员两个角色。 用户注册登录后可以浏览鲜花,浏览公告&…...
网页视频下载软件免费版/seo翻译
一、maven各个命令的区别: 1、maven clean 清空target下的文件2、maven compile 编译(在target下生成.class文件) 一般使用:mvn clean package 先清缓存再打包注意:如果使用的是Eclipse的maven插件,插件默认…...
网站建设济南有做的吗/外贸怎么建立自己的网站
用域策略脚本实现把客户端administrator帐号密码统一更改 在写这贴之前,我在网上找过很多关于这个方面的资料,看到他们都是说的差不多,但是当一个新手来弄的话就比较难实现了。非常感谢网上的朋友们对我的帮助,我写这帖子就是想要…...