请不要付费,只是把历史笔记发布,包含专栏内容总结。
专栏总结1:基础网络相关
专栏总结2:数据结构和算法
专栏总结3:操作系统和计算机原理
专栏总结4:Linux和linux内核
专栏总结5:mysql相关
专栏总结6:redis相关专栏总结7:中间件Nginx、消息队列
专栏总结java1:类型和String、反射
专栏总结java2:集合
专栏总结java3:类接口相关
专栏总结java4:异常
专栏总结java5:线程/多线程并发
专栏总结java6:jvm
专栏总结java7:jdk
专栏总结java8:Socket编程 nio
专栏总结java9:MyBatis+hibernate
专栏总结java10:Spring MVC
专栏总结java11:springboot
专栏总结java12:springcloud
专栏总结java13:dubbo
一、操作系统基本结构
linux系统结构:
操作系统也是一门非常重要的知识,内容也很多,例如:进程和线程以及他们的区别,内存和虚拟内存等.
程序如何运行
二、程序
程序装入和链接:https://blog.csdn.net/hguisu/article/details/5713099
1、程序如何运行
在多道程序环境下,要使程序运行,必须先为之创建进程。而创建进程的第一件事,便是将程序和数据装入内存。如何将一个用户源程序变为一个可在内存中执行的程序,通常都要经过以下几个步骤:
首先是要编译,由编译程序(Compiler)将用户源代码编译成cpu可执行的目标代码,产生了若干个目标模块(Object Module)(即若干程序段),
其次是链接,由链接程序(Linker)将编译后形成的一组目标模块(程序段),以及它们所需要的库函数链接在一起,形成一个完整的装入模块(Load Module);
最后是装入,由装入程序(Loader)将装入模块装入内存。
三、进程和线程
进程理论:https://blog.csdn.net/hguisu/article/details/1910803
linux进程:https://blog.csdn.net/hguisu/article/details/6128274
进程调度:https://blog.csdn.net/hguisu/article/details/1910814
1、进程和线程:
进程:程序在一个数据集上的一次运行过程。是操作系统资源分配的基本单位。
在Windows下,进程又被细化为线程,也就是一个进程下有多个能独立运行的更小的单位. 进程还拥有一个私有的虚拟地址空间,该空间仅能被它所包含的线程访问。
线程:是进程中的一个实体,是被操作系统独立调度和执行的基本单位。一个进程包含一个或多个线程。
线程只能归属于一个进程并且它只能访问该进程所拥有的资源。当操作系统创建一个进程后,该进程会自动申请一个名为主线程或首要线程的线程。主线程将执行运行时宿主, 而运行时宿主会负责载入CLR。
2、进程状态
进程状态五态模型:
运行状态(Running):当一个进程正在处理机上运行时。
就绪状态(Ready):一个进程获得了除处理机之外的一切所需资源,一旦得到处理机即可运行.
等待状态又称阻塞状态(Blocked):一个进程正在等待某一事件而暂停运行时。如等待某资源,等待输入/输出完成。
创建状态(NEW):一个进程正在被创建,还没被转到就绪状态之前的状态。
结束状态(Exit):一个进程正在从系统中消失时的状态,这是因为进程结束或由于其他原因所导致。
3、进程之间究竟有哪些通信方式?
windows的进程间的通信方式有: 1.文件映射;2. 共享内存(是文件映射的一种特殊情况);3.邮件槽(mailslot)(点对点消息队列); 4.匿名管道;5;命名管道; 6. 剪贴板;7.动态数据交换;8.对象链接与嵌入;9.远程过程调用;10.动态链接库;11.socket;12.WM_COPYDATA .
linux进程间通信的方式有:1.管道 2.信号量 3.共享内存 4.消息队列 5.套接字 6.信号
windows和linux共有的进程间通信方式:1. 消息(linux中叫做信号) 2. 共享内存 3. 邮槽 4. 管道 5.socket
linux下进程间通信的几种主要手段简介:
管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;
信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数);
报文(Message)队列(消息队列):消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。
套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字。
4、进程什么组成的?
第一,进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。
第二,进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋予程序生命时,它才能成为一个活动的实体,我们称其为进程。
linux进程结构:
Linux中一个进程在内存里有三部分数据,就是“数据段”、“堆栈段”和“代码段”。基于I386兼容的中央处理器,都有上述三种段寄存器,以方便操作系统的运行,如图所示:
代码段:是存放了程序代码的数据,即存放CPU执行指令的集合。假如机器中有数个进程运行相同的一个程序,那么它们就可以使用同一个代码段。
数据段:存放程序的全局变量、常数及动态数据分配的数据空间,即被执行指令所访问的数据。
堆栈段: 存放的就是子程序的返回地址、子程序的参数及程序的局部变量。堆栈段包含在进程控制块PCB(Process Control Block)中。PCB处于进程核心堆栈的底部,不需要额外分配空间。堆栈段包括堆和栈:
堆(heap):堆是用于存放进程运行中被动态分配的内存段,它大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)
栈(stack):栈是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味这在数据段中存放变量)。除此以外在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也回被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上将我们可以把堆栈看成一个临时数据寄存、交换的内存区。
4、进程调度算法?
1. 先来先服务调度算法FCFS。FCFS算法比较有利于长作业(进程),而不利于短作业(进程)。由此可知,本算法适合于CPU繁忙型作业, 而不利于I/O繁忙型的作业(进程)。
2、短作业(进程)优先调度算法。短作业(进程)优先调度算法(SJ/PF)是指对短作业或短进程优先调度的算法,该算法既可用于作业调度, 也可用于进程调度。但其对长作业不利;不能保证紧迫性作业(进程)被及时处理;作业的长短只是被估算出来的。
3、优先权调度算法的类型。
4、时间片轮转法。时间片轮转法一般用于进程调度,每次调度,把CPU分配队首进程,并令其执行一个时间片。 当执行的时间片用完时,由一个记时器发出一个时钟中断请求,该进程被停止,并被送往就绪队列末尾;依次循环。
4、CPU利用率:
CPU利用率=CPU时间/总时间
单任务系统(单个CPU),中有两个程序,A程序顺序:
使用CPU 10秒,使用设备甲 5秒,
使用CPU 5秒,使用设备乙10 秒,
最后使用CPU 10秒,B程序按顺序:
使用甲设备10秒 使用CPU 10秒,
使用设备乙5秒, 使用CPU 5秒,
使用设备乙10秒,请问在并行环境下执行A,B,两个程序,假设A程序先执行,则CPU的利用率为多少?
谓A/B并行,只是A、B程序同时执行,但是CPU在同一个时间点,只响应A或者B,也就是说,并行环境下,A程序在使用甲设备时CPU可以执行B程序。
答案;(10+10+10+10)/(10+10+5+10+10)89%
5、linux是个进程树:父进程和子进程:
一个进程创建新进程称为创建了子进程(Child Process)。相反地,创建子进程的进程称为父进程。所有进程追溯其祖先最终都会落到进程号为1的进程身上,这个进程叫做init进程,是内核自举后第一个启动的进程。init进程扮演终结父进程的角色。
整个linux系统的所有进程也是一个树形结构。树根是系统自动构造的,即在内核态下执行的0号进程,它是所有进程的祖先。由0号进程创建1号进程(内核态),1号负责执行内核的部分初始化工作及进行系统配置,并创建若干个用于高速缓存和虚拟主存管理的内核线程。随后,1号进程调用execve()运行可执行程序init,并演变成用户态1号进程,即init进程。
*父进程与子进程的差异 :下图中,进程A为父进程,进程B为子进程:
5、创建子进程:
fork()函数用于从已存在的进程中创建一个新的子进程,在 pid=fork();语句之前只有父进程在运行,而在 之后,父进程和新创建的子进程都在运行,子进程拷贝父进程的代码段,所以子进程中同样有
#include<unistd.h>
int main( )
{
pid_t pid;
pid=fork();
if((pid)<0)
{printf(“fork error!\n”);
exit(1);
}
else if(pid=0)
printf(“child process isprinting.IDis %d\n”,getpid());
else
printf(“parent process is printing. ID is%d\n”,getpid());
}}
四、内存
操作系统内存:https://blog.csdn.net/hguisu/article/details/5713164
linux内存管理:https://blog.csdn.net/hguisu/article/details/5713164
linux了解内存使用:https://blog.csdn.net/hguisu/article/details/7403855
内存管理包括:虚拟内存、分页、分段、分页系统地址映射、内存置换算法。
1、虚拟内存
虚拟内存地址就是每个进程可以直接寻址的地址空间,不受其他进程干扰。每个指令或数据单元都在这个虚拟空间中拥有确定的地址。
虚拟内存就是进程中的目标代码,数据等虚拟地址组成的虚拟空间
2、分页、分段
分页:将程序的逻辑地址空间划分为固定大小的页(page),而物理内存划分为同样大小的页框(page frame)。程序加载时,可将任意一页放人物理内存中任意一个页框,这些页框不必连续,从而实现了离散分配。
分段:在段式存储管理中,将程序的地址空间划分为若干个段(segment),这样每个进程有一个二维的地址空间。
分页可以有效提高内存利用率,分段可以更好的满足用户需求。
3、分页系统地址映射
在页式系统中,指令所给出的地址分为两部分:逻辑页号和页内地址。
原理:CPU中的内存管理单元(MMU)按逻辑页号通过查进程页表得到物理页框号,将物理页框号与页内地址相加形成物理地址(见图4-4)。
逻辑页号,页内偏移地址->查进程页表,得物理页号->物理地址:
图4-4 页式管理的地址变换
上述过程通常由处理器的硬件直接完成,不需要软件参与。通常,操作系统只需在进程切换时,把进程页表的首地址装入处理器特定的寄存器中即可。一般来说,页表存储在主存之中。这样处理器每访问一个在内存中的操作数,就要访问两次内存:
第一次用来查找页表将操作数的 逻辑地址变换为物理地址;
第二次完成真正的读写操作。
这样做时间上耗费严重。为缩短查找时间,可以将页表从内存装入CPU内部的关联存储器(例如,快表) 中,实现按内容查找。此时的地址变换过程是:在CPU给出有效地址后,由地址变换机构自动将页号送人快表,并将此页号与快表中的所有页号进行比较,而且这 种比较是同时进行的。若其中有与此相匹配的页号,表示要访问的页的页表项在快表中。于是可直接读出该页所对应的物理页号,这样就无需访问内存中的页表。由于关联存储器的访问速度比内存的访问速度快得多。
4、内存置换算法
1、缺页中断定义:
现代操作系统通过虚拟内存技术来扩大物理内存,虚拟内存每一页都映射在物理内存或磁盘上所以虚拟内存会比物理内存大,程序里访问的是虚拟地址,当程序访问页映射在磁盘上时,就会发生缺页中断,调用中断处理程序将页载入物理内存。例如:32位Linux的每个用户进程都可以访问4GB的线性地址空间, 而实际的物理内存可能远远少于4GB. 采用分页机制 ,Linux仅把可执行映像的一小部分装入物理内存. 当需要访问未装入的页面时 . 系统产生一个缺页中断, 把需要的页读入物理内存。
缺页中断:即指的是当应用程序试图访问已映射在虚拟地址空间中,但是并未被加载在物理内存中的一个分页时,产生一个页不存在的中断,需要操作系统将其调入物理内存后再进行访问。在这个时候,被内存映射的文件(映像)实际上成了一个分页交换文件。
名为“缺页中断”或者“页缺失”错误,但实际上这并不一定是一种错误。而且这一机制对于利用虚拟内存来增加程序可用内存空间的操作系统。
2、缺页中断的次数
中断次数=进程的物理块数+页面置换次数。
缺页中断率=(缺页中断次数 / 总访问页数 )
3、页面置换算法
当发生缺页中断时,如果操作系统内存中没有空闲页面,则操作系统必须在内存选择一个页面将其移出内存,以便为即将调入的页面让出空间。而用来选择淘汰哪一页的规则叫做页面置换算法。
几种缺页中断算法(FIFO,LRU与LFU)的实现过程:
在分页虚拟存储管理的系统中,有一用户进程,它依次要访问的页面序列是序列7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1。 假定分配给该进程的页数(物理块)为3且进程初始时未装载页面(意思就是进程只能使用三块内存)。计算缺页次数和缺页率?那么采用FIFO、LRU、OPT调度算法产生的缺页中断数各为多少?缺页中断率各为多少?1)、先进先出(FIFO)
优先淘汰最早进入内存的页面,亦即在内存中驻留时间最久的页面。该算法实现简单,只需把调入内存的页面根据先后次序链接成队列,设置一个指针总指向最早的页面。但该算法与进程实际运行时的规律不适应,因为在进程中,有的页面经常被访问。
利用FIFO置换算法时的置换图:
访问页面 7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1 物理块1 7 7 7 2 2 2 4 4 4 0 0 0 7 7 7 物理块2 0 0 0 3 3 3 2 2 2 1 1 1 0 0 物理块3 1 1 1 0 0 0 3 3 3 2 2 2 1 缺页否 √ √ √ √ √ √ √ √ √ √ √ √ √ √ √
进程访问页面2时,把最早进入内存的页面7换出。然后访问页面3时,再把2, 0, 1中最先进入内存的页换出。由图可以看出,利用FIFO算法时进行了 12次页面置换。发生缺页中断的次数为15。
2)、最近最久未使用(LRU)置换算法
选择最近最长时间未访问过的页面予以淘汰,它认为过去一段时间内未访问过的页面,在最近的将来可能也不会被访问。该算法为每个页面设置一个访问字段,来记录页面自上次被访问以来所经历的时间,淘汰页面时选择现有页面中值最大的予以淘汰。
对上面的实例釆用LRU算法进行页面置换,如图所示。进程第一次对页面2访问时,将最近最久未被访问的页面7置换出去。然后访问页面3时,将最近最久未使用的页面1换出。
访问页面 7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1 物理块1 7 7 7 2 2 4 4 4 0 1 1 1 物理块2 0 0 0 0 0 0 3 3 3 0 0 物理块3 1 1 3 3 2 2 2 2 2 7 缺页否 √ √ √ √ √ √ √ √ √ √ √ √
3). 最佳置换算法(OPT)
最佳(Optimal, OPT)置换算法所选择的被淘汰页面将是以后永不使用的,或者是在最长时间内不再被访问的页面,这样可以保证获得最低的缺页率。但由于人们目前无法预知进程在内存下的若千页面中哪个是未来最长时间内不再被访问的,因而该算法无法实现。
对上面的实例釆用OPT算法进行页面置换,如图所示:
访问页面 7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1 物理块1 7 7 7 2 2 2 2 2 7 物理块2 0 0 0 0 4 0 0 0 物理块3 1 1 3 3 3 1 1 缺页否 √ √ √ √ √ √ √ √ 进程运行时,先将7, 0, 1三个页面依次装入内存。进程要访问页面2时,产生缺页中断,根据最佳置换算法,选择第18次访问才需调入的页面7予以淘汰。然后,访问页面0时,因为已在内存中所以不必产生缺页中断。访问页面3时又会根据最佳置换算法将页面1淘汰……依此类推,如图所示。从图中可以看出釆用最佳置换算法时的情况。
可以看到,发生缺页中断的次数为9,页面置换的次数为6。