进程的组成
在操作系统中,一个创建和销毁一个进程是十分重量级的。
因为一个进程由以下组成:
用户的地址空间、实现进程间同步的通信机制、申请I/O设备、一张有核心进程维护的地址映射表、进程控制块(PCB)
这些资源对操作系统来说都是十分重量级的。因此就产生了线程。
线程的组成
线程控制块(TCB)、程序计数器、寄存器、堆栈空间、状态数、优先级
相对进程而言,线程所需要的资源就显得十分轻量级了。线程与线程之间的隔离新也没有那么强,线程之间可以相互协作。
线程和进程的区别
事实上,线程和进程最大的区别就是进程和线程向操作系统申请的资源不同,其次进程需要内核的直接或者间接支持,而线程不需要。
进程通信
管道、消息传递、共享存储介质、C/S架构(套接字)
进程对换
实际上,在进程并发执行的时候,如果将所有的进程都同时存储到内存中,这样很多没有在运行的程序也保存在内存中,就降低了内存的使用率,所以操作系统会先将阻塞的线程移至外存。
进程队列
进程之间并发执行,操作系统为了更好的管理这些进程,分别使用几个队列来管理不同状态的进程。
例如:
阻塞队列,就绪队列等。
中断控制器
没有中断控制器之前,所有的应用都可以向CPU发送中断请求,CPU为了处理这些中断,处理逻辑什么的变的十分混乱。因此就引入了中断处理器。所有的应用都将中断请求发送给中断控制器,中断控制器来判断哪个中断请求的优先级更高,在将这些请求转交给CPU处理。
进程调度算法
为了提高cpu的使用效率,所以操作系统采用一种走走停停的工作方式,让几个进程 “同时” 运行。
1、先来先服务(First Come First Service)
顾名思义,就是先启动的先运行。
2、短作业优先法(Short Job First)
作业时间越短,越优先执行。
缺点十分明显必须要预先知道作业的执行时间。
3、优先级调度
等待的时间越长优先级越高。
4、高响应比优先调度
综合了等待时间和作业执行时间,是一种折中的调度方式。
5、轮询方式
按照启动的顺讯一个接着一个运行。
6、抢占式
所有正在等待cpu资源的所有进程共同去抢夺cpu资源,谁抢到了资源,谁就运行,但是这种抢夺不是任意性的,还是按照一定的规则。
7、非抢占式
现在几乎不使用了,这种方式就是让一个进程一直运行。
分时
cpu的执行速度十分快,如果单纯只执行一个程序,cpu的许多性能都没有利用上,造成了资源的过剩,而且操作系统也只能运行单个服务。为了能够运行多个程序,提高cpu的使用率,因此操作系统采用一种时间片的设计。
那个程序获得了时间片,那个程序就能够运行,然后运行完之后,cpu在切换到其他获得时间片的程序,一直进行程序的切换,由于cpu的告诉运转,对于人类来说就像是同时在运行。
通常时间片的时间单位都是一纳秒的几千分之一。
资源
1、可重用型资源
2、可抢占式资源。cpu、内存
3、不可抢占式资源。例如:打印机
产生死锁的条件
1、互斥条件
2、请求和保持条件
3、不可抢占条件
4、循环等待条件
处理死锁的方式
1、预防死锁
2、避免死锁
3、解除死锁:让死锁的线程回收该资源,线程重新进入阻塞状态。
同步的原子性操作问题
由于很多时候线程并发访问同一个资源,就会造成同步问题,而对于写操作就务必会有两个动作,一个是读数据,一个是写数据,对于这种情况,操作系统给了一种解决方式:加锁。
但是在加锁的过程中,需要有一个变量标识是否有线程对这个资源的占用,而这个操作这个变量又涉及到读写操作,这貌似使得加锁编程了不可能,操作系统从硬件上给定了加锁对标识变量的判断与修改是原子性操作(也就是说线程读取标识是否加锁变量与修改标识是否加锁变量的值是不可分割,不可中断的),然后开发人员就可以通过这种硬件给定的函数去实现软件同步。
其实这种原子性操作,操作系统的实现方法很简单就是在读、写的过程中,不让操作系统产生中断操作,从而就实现了原子操作。
自旋锁
如果一个线程要操作一个共享变量的值,那么他要先获取这个资源的锁,而要获取这个资源的锁,又要先判断锁的标识变量,判断是否有人占用,线程一直循环去判断这个变量,一旦他为false,表示没有人占用,就立马将他改为true。
正因为这种一直循环的特点,因此这种锁被称为自旋锁。这种循环的方式会占用大量的cpu资源,因此操作系统又产生了阻塞队列,用来管理这些等待锁的线程。
在递归获取锁的时候,很容易因为这种循环的特点而造成死锁。我们称这种情况为不可重入性,为了解决这种情况,操作系统给锁对象加了一个程序计数器,每次获得这把锁,计数器就加1,释放锁就减1;从而保证了锁的可重入性。
线程同步方式
1、互斥量。
2、信号量。
3、自旋(利用死循环的方式实现的)
4、管程。
5、阻塞队列,jdk中就提供了BlockingQueue。
存储器
cpu:寄存器
主存:
1、高速缓存器
2、主存储器(内存)
3、磁盘缓存
辅存
1、固定磁盘
2、可移动存储介质。
内存分配
1、固定分区分配
固定内存大小,现已基本不使用,不灵活,而且容易造成碎片。
2、单一连续分配
整个内存空间由程序独占。
3、动态分区分配
动态分配内存,通过一张内存分区表管理,内存分区的记录,记录那些分区使用情况,分区大小,分区始址。
碎片的产生
程序对磁盘进行大量分区(此处是指运行期间的内存分区),由于程序的内存分配十分复杂,而且很多内存分区后,有一小部分内存没有被使用,这就导致了这部分内存空间不能被其他程序使用,这就是碎片的产生。
或者说程序使用完了,操作系统将这些区域的数据回收了,这些区域又没有被重新使用,一直空缺着。
内存分页
由于程序的运行,内存的大小的需求不定,因此操作系统使用分页的方式解决这种问题,每页1-8kb,由一张分页映射表管理页的联系。
由于内存进行了分页,所以要程序的位置,需要先找打在第几页,然后在去该页中找映射的真实地址,这样的速度就慢了很多,因此操作系统引入了快表的方式。
快表的方式就和索引很类似,一般在块表中保存的地址都是这些数据经常访问的地址。
虚拟内存
很多时候进程运行需要大量的内存空间,但实际上我们的硬件并没有这么大的内存,所以将程序需要运行的部分加载到内存中,而大部分不需要运行的数据,先转移到硬盘上,这个操作是不可见的,用户看来是整个程序都加载进内存了,这种感受是 “虚” 的,因此被称为虚拟内存。
虚拟页面就是分配给程序使用的,但是程序运行的数据并不会存在虚拟内存中,而是存在物理内存中,虚拟页面只用来做一个记录,而页表负责做物理地址和虚拟地址的的映射。
在程序运行的时候由MMU内存管理单元来计算映射规则。
缺页处理
程序并不是一次性全部加载,而是采用按需加载,使用这种方式,那在运行的过程中就肯定会遇到一些没有加载过的数据,因此操作系统这时候就采用缺页管理的方式将这些数据加载。
也正是因为这种按需加载和缺页的处理,通常一个程序都被大卸八块的加载,并且这些块和块之前分配的内存也有可能不在同一个区域。但是每一块的数据的内存分配肯定是连续的。这种分配也符合局部性原理。
段表
由于程序运行期间会产生很多不同类型的数据,例如只读数据,共享数据。操作系统为了更好的管理这些数据,就将这些数据分配到不同阶段的空间内,而段与段之间也采用进程隔离的那种方式来进行分段。
进程隔离
由于采用这种分页的形式给程序分配内存,如果有一些恶意程序故意操作自己的内存地址,超出自己程序分配内存的范围,不就能读取到其他程序的数据了吗。
操作系统采用了一种十分简单的方式,操作系统使用两个存储单元来记录程序运行时内存的最高位和最低位,当程序运行操作的内存地址超出了这个方法抛出异常。
DMA(Direct Memory Access)
由于I/O设置对于数据的操作十分缓慢,为了解决大量数据要将硬盘的数据加载到内存,或者说从内存保存到硬盘上。
操作系统就引入了DMA,DMA是如何实现数据的读取的呢?
DMA通过总线建立起了CPU与内存还有外设之间的联系。
如下图:
假设现在CPU想获得键盘的输入,CPU告诉DMA,DMA告诉键盘,键盘输入数据,将DMA获得数据将数据存在内存,CPU就可以直接访问了。
总线
cpu和一些外设(鼠标、键盘、显示器)传输数据的载体就是总线,所以说总线的作用十分重要。
文件系统
因为内存容量有限,且不能长期保存。所以要把这些数据以某一种形式管理,这种形式就是文件。
文件的数量、种类特别多,就产生了文件系统。
文件系统就是管理文件的一个管理者。
操作系统中其实就把文件当成了一个文件描述符(FD),文件描述符中记录了文件的状态信息,会根据文件的读写操作,文件描述符的状态也会发生变化,而这些变化都是由操作系统控制的。例如:读、写状态。
类似于java中的nio其实就是基于这种文件描述符的方式从而实现单线程处理相对来说较高的并发操作的。
文件的打开:
实际上就是将指定文件在外存上的物理地址,复制到内存中。操作系统会将文件的这些物理地址管理成一个页表,做成索引返回给用户。用户就可以利用这些索引去操作文件了,避免对该文件的重复检索。
文件的关闭:
就是将内存中制作出来的文件索引以及页表删除掉。
外存分配方式
1、连续分配。
连续分配的策略十分符合局部性原理的特点。一般文件存储的外存空间是连续的。
缺点:一般需要知道具体的存储空间大小。类似于顺序表。
2、链接分配。
类似于链表。
文件系统格式
FAT格式:
FAT引入了卷的概念,支持将一个物理磁盘分成4个逻辑磁盘,如果你电脑的磁盘是FAT格式的,那么最多只支持分成四个分区。例如:C、D、E、F四个逻辑磁盘。
每一个逻辑磁盘上都维护了一个自己的FAT表,用于管理这个逻辑磁盘的结构信息。
FAT12格式:
在FAT的基础上引入了盘块的概念,盘块就是外存的基本分配单位。但是由于盘块大小较小并且FAT只支持4个逻辑分区,因此能够表示的外存容量特别小。
为了适配磁盘容量的不断增大,将盘块的基本单位又改成了簇,簇能够表达的数据空间就比较大了。
后面又诞生出来了FAT16,FAT32,这些格式都是为了解决外存的碎片以及外存容量的扩展而诞生的。
NTFS:
能够很好支持超大容量的磁盘。
文件的撤销与恢复
文件操作为了实现容错,文件的修改,写这些操作也使用了事务的概念去实现数据的一致性原则。
文件系统会为文件操作维护一个事务记录,这个事务记录可以看成就是一个日志。可以根据这个事务记录来进行事务的回滚。
文件系统的ctrl+z和ctrl+y也就是基于事务记录实现的。
线程同步机制
互斥锁:
互斥锁的实现过程,给共享对象设置一把锁,当有线程去操作这个对象的时候,必须要先获得这个共享对象的锁。
同一时刻只能有一个线程对这个共享对象进行读/写操作。这就造成了读的时候的效率问题。
共享锁:
同一个时刻允许多个线程去对同一个共享对象进行读操作,但是不允许任何一个线程对其进行写操作。
利用互斥锁和共享锁就可以实现,只有一个事务对共享对象进行写操作,可以同时有多个事务进行读操作。
主从复制
在文件系统中,还有一种主从复制的方式。将文件信息复制多份,分发到各个地方,其他地方的文件也可以用来使用。但是为了让这个多个数据保持数据的一致性,在系统运行过程中,总是会不断的对其他地方的那些文件进行修改,永远和主文件的数据保持一致。
这是备份文件之间都保留着对其他备份文件有着一个软连接索引。修改一个备份数据,其他的几个备份数据都会立马得到更新。
缓冲区
数据缓冲区除了减少进程之间的通信之外,还有就是可以降低中断处理器的频率,从而减少线程的TCB(线程控制块)的现场恢复次数。
进程间通信一般是由三部分组成:消息机制、共享存储器和信号量。
分组交换网
1、报文交换方式
网络请求采用报文的方式去存储/转发,但是这种方式一直发请求,然后转发,请求的次数太多。因此就引入了分组交换方式。
2、分组交换方式
分组交换方式和报文交换方式一样,都是采用存储/转发的方式传输信息,与报文交换方式不同的是,分组交换方式,把报文分组,并且定一个长途,然后以分组为单位去传输。提高了信息的传输。
3、分组交换网
以分组为传输单位,将正文和分组头划分,每经过一个通信子网节点,都进行信息的差错检测。如果没有出错则进行传递到下一个节点,直到传递到目标主机。
流量控制
在分组交换网中,信息都采用存储/转发的方式。在每一个网络节点上,都有一定数量的缓冲区,如果不进行流量控制,当发送方发送的数据太快,而接受方还没有接受到数据,这样中间网络节点上的缓冲区就会使用晚,就会造成数据传输异常。
TCP
在通信之前,应先与另外一端进行连接,数据传输完毕之后,应拆除连接。这就是tcp协议的三次握手。
为了确保数据传输的可靠性,tcp采用确认和重发措施。即接受方每接受到数据时,都要进行差错检测,当正确时,都应更具数据段中的发送序号,给发送方也发送回一个用于确认的ACK数据段。如果接受方接受的数据有错,则要求发送方重发。
此外,正常情况下,要控制发送方发送数据段的数据不应超过接受方接受数据的能力,对于紧急数据段,则不受流量控制。
最后,在数据传输完成之后,接受方还得向发送方发送断开连接的ACK,来拆除连接。
为什么TCP要进行三次握手,其实就是在确认双方的发信和收信能力。
发送/等待方式。
当源(N)实体发出一数据单元后,要等待目标系统的(N)实体发回 应答,然后源(N)实体再根据应答情况决定下一步的操作。若对方发回的是确认,源(N)实体 可继续发送下一个数据单元;若对方发回的是否认应答,则原(N)实体应重发该数据单元。
UDP
tcp由于通信之前要建立端与端之间的连接,而且每次传输数据都要进行差错检测,确认,错误重发等操作。因此,对于一些数据要求不是那么的重要的情况下,tcp的传输效率就变得十分低了。
就引入了UDP,udp协议是一种无连接,不可靠的协议,他不要求传输之前先建立连接,也没有进行消息确认,差错控制,单方面的一直发送数据出去给接受方,不管接受是否接受到。
连续发送方式
源(N)实体在发出一个数据单元后,无需等待对方的确认,便可继 续发送下一个数据单元,直到全部数据发送完毕,或按某种规则暂停发送数据为止。这样 就消除了每包发送后的等待时间。收方可在收到几个数据单元后,汇总起来一起发回一个 确认应答。显然,这种连续发送方式提高了传输效率。
ip地址
在一个偌大的互联网,要想找到某一台主机,就要有一个路径,而ip地址就是寻找主机所在地址的一个标识。
ip地址共有32位,一般由两部分组成,网络标识和主机标识,不同类别的ip地址每个段所表示的意思也不一样。
域名
ip地址适合网络识别和处理,但是利于理解和记忆,因此就产生了域名。一个域名可以对应多个ip地址,一个ip地址只能对应一个域名。
DNS域名解析
域名服务器有很多,他的结构就像是金字塔状的,每一层只能找到他的直接下级域名服务器。
所以域名解析,一般是将将域名发送给顶级域名服务器,然后顶级域名服务器,抽取出来这个域名的下级域名,然后又将域名交给下以及域名服务器,最终解析出ip地址。
数据加密
1、明文:需要加密的文本。
2、密文:明文加密过后的文本。
3、加密算法:明文到密文转换的过程。
4、密钥:明文到密文转换的关键参数。
网络传输加密技术
对每一个传输的节点进行链路加密。
网络安全防治
1、口令(密码)长度限制。
2、自动断开连接。例如:输错三次当天不允许输入。
3、屏蔽回显。
4、记录和报告登录信息。