死锁
1.产生死锁的四个必要条件
- 互斥条件:进程要求对所分配的资源进行排它性控制,即在一段时间内某资源仅为一进程所占用。
- 请求和保持条件:当进程因请求资源而阻塞时,对已获得的资源保持不放。
- 不可抢占:进程已获得的资源在未使用完之前,不能被抢占,只能在使用完时由自己释放。
- 循环等待:循环等待环形链。
2.预防(避免)死锁
我上面说了产生死锁的四个必要条件,为了避免死锁,我们只要破坏产生死锁的四个条件中的其中一个就可以了。现在我们来挨个分析一下:
- 破坏互斥条件 :这个条件我们没有办法破坏,因为我们用锁本来就是想让他们互斥的(临界资源需要互斥访问)。
- 破坏请求与保持条件 :一次性申请所有的资源。
- 破坏不可抢占条件 :占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。
- 破坏循环等待条件 :靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件。
内存管理
内存管理主要是做什么?
主要负责内存的分配与回收(malloc函数:申请内存,free函数:释放内存),另外地址转换也就是将逻辑地址转换成相应的物理地址也是内存管理做的事情。
常见的几种内存管理机制
连续分配管理方式:分配一个连续的内存空间,如块式管理。
非连续~:允许分配离散或则不相邻的内存空间,如页式管理和段式管理。
- 块式管理:远古时代的计算机操系统的内存管理方式。将内存分为几个固定大小的块,每个块中只包含一个进程。如果程序运行需要内存的话,操作系统就分配给它一块,如果程序运行只需要很小的空间的话,分配的这块内存很大一部分几乎被浪费了。这些在每个块中未被利用的空间,我们称之为碎片。
- 页式管理:将 程序的逻辑地址空间划分为固定大小的页(page),而物理内存划分为同样大小的页框(pageframe)。程序加载时,可将任意一页放人内存中任意一 个页框,这些页框不必连续,从而实现了离散分配。提高了内存利用率,减少了碎片。页式管理通过页表对应逻辑地址和物理地址。
- 段式管理:页式管理虽然提高了内存利用率,但是页式管理其中的页并没有实际含义。段式存储管理要求每个作业的地址空间按照程序自身的逻辑划分为若干段,如代码段、数据段、共享段。每个段都有一个唯一的内部段号。以段为单位进行分配,每个段在内存中占连续空间,但各段之间可以不相邻
- 段页式管理:段页式管理机制结合了段式管理和页式管理的优点。简单来说段页式管理机制就是把主存先分成若干段,每个段又分成若干页。
快表和多级页表
在分页内存管理中,很重要的两点是:
- 虚拟地址到物理地址的转换要快。-------快表
- 解决虚拟地址空间大,页表也会很大的问题。--------多级页表
快表
为了解决虚拟地址到物理地址的转换速度,操作系统在 页表方案 基础之上引入了 快表(存放在单独的寄存器中) 来加速虚拟地址到物理地址的转换。我们可以把块表理解为一种特殊的高速缓冲存储器(Cache),其中的内容是页表的一部分或者全部内容。作为页表的 Cache,它的作用与页表相似,但是提高了访问速率。由于采用页表做地址转换,读写内存数据时 CPU 要访问两次主存。有了快表,有时只要访问一次高速缓冲存储器,一次主存,这样可加速查找并提高指令执行速度。
使用快表之后的地址转换流程是这样的:
- 根据虚拟地址中的页号查快表;
- 如果该页在快表中,直接从快表中读取相应的物理地址;
- 如果该页不在快表中,就访问内存中的页表,再从页表中得到物理地址,同时将页表中的该映射表项添加到快表中;
- 当快表填满后,又要登记新页时,就按照一定的淘汰策略淘汰掉快表中的一个页。
多级页表
引入多级页表的主要目的是为了避免把全部页表一直放在内存中占用过多空间,特别是那些根本就不需要的页表就不需要保留在内存中。多级页表属于时间换空间的典型场景。(局部性原理)
页式管理和段式管理的共同点和区别
- 共同点:
- 分页机制和分段机制都是为了提高内存利用率,较少内存碎片。
- 页和段都是离散存储的,所以两者都是离散分配内存的方式。但是,每个页和段中的内存是连续的。
- 区别:
- 页的大小是固定的,由操作系统决定;而段的大小不固定,取决于我们当前运行的程序。
- 分页仅仅是为了满足操作系统内存管理的需求,而段是逻辑信息的单位,在程序中可以体现为代码段,数据段,能够更好满足用户的需要。
虚拟内存
1.什么是虚拟内存?
虚拟内存使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。与没有使用虚拟内存技术的系统相比,使用这种技术的系统使得大型程序的编写变得更容易,对真正的物理内存(例如RAM)的使用也更有效率。目前,大多数系统都使用了虚拟内存,如Windows家族的“虚拟内存”;Linux的“交换空间”等。
不要单纯的认为虚拟内存只是“使用硬盘空间来拓展内存”的技术,这只是其中之一。虚拟内存的重要意义是它定义了一个连续的虚拟地址空间,而且把内存拓展到硬盘空间。
2.局部性原理
程序在执行的时候往往呈现局部性规律,也就是说在某个较短的时间段内,程序执行局限于某一小部分,程序访问的存储空间也局限于某个区域。
- 时间局部性:如果程序中的某条指令一旦执行,不久以后该指令可能再次执行;如果某数据被访问过,不久之后该数据可能再次被访问。产生局部性的典型原因,是由于在程序中存在着大量的循环操作。
- 空间局部性:一旦程序访问了某个存储单元,不久以后其附近的存储单元可能也被访问。因为指令通常顺序存放,顺序执行。数据也一般以向量,数组,表等形式聚簇存储的。
3.虚拟存储器
基于局部性原理,在程序装入时,可以将程序的一部分装入内存,其余部分留在外存,就可以启动程序执行。执行过程中,如果访问的信息不在内存,则将所需部分调入内存,继续执行。另一方面,操作系统将暂时不用的内容换到外存上。由于外存往往比内存大很多,计算机好像为用户提供了一个比实际内存大得多的存储器–虚拟存储器。
实际上,这是一种时间换空间的策略。用CPU的计算时间和页的调入调出时间,换来了一个虚拟的更大的空间来支持程序的运行。
4.虚拟内存的技术实现
虚拟内存的实现需要建立在离散分配的内存管理方式的基础上。
- 请求分页存储管理
- 请求分段存储管理
- 请求段页式存储管理
(请求分页和分页存储管理的区别:请求分页存储管理建立在分页管理之上。他们的根本区别是是否将程序全部所需的地址空间都装入主存。)
不管是上面三种哪种实现方式,我们都需要
- 一定容量的内存和外存。
- 缺页中断:如果需执行的指令或访问的数据未在内存(称为缺页或缺段),则由处理器通知操作系统将相应的页面调入内存,继续执行。
- 虚拟地址空间:逻辑地址到物理地址的变换。
4.页面置换算法
当发生缺页中断时,操作系统需要在内存选择一个页面将其移出内存,以便为即将调入的页面让出空间。以下是几种淘汰规则。
- OPT页面置换算法(最佳页面置换算法):淘汰以后永不使用的,或是最长时间内不被访问的。无法实现。因为无法预知未来。
- FIFO (first in first out):先进先出页面置换算法。
- LRU:最近最久未使用。
- LFU:最少使用。使用频率最少。
常见面试题
1.用户态和内核态的区别
两种不同的CPU状态
内核态(Kernel Mode):运行操作系统程序,操作硬件。
用户态(User Mode):运行用户程序。
- 处于用户态执行时,进程所能访问的内存空间和对象受到限制,其所处于占有的处理器是可被抢占的
- 处于内核态执行时,则能访问所有的内存空间和对象,且所占有的处理器是不允许被抢占的。
用户态切换到内核态的三种情况
- 系统调用 这是用户态进程主动要求切换到内核态的一种方式,**用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作。**如fork()实际上就是执行了一个创建新进程的系统调用。
- 异常 当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态
- 外围设备的中断 当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。
2.内核
简单来说,内核是一个操作系统的核心。它负责管理系统的进程、内存、设备驱动程序、文件和网络系统等等,决定着系统的性能和稳定性。是连接应用程序和硬件的桥梁。
内核就是操作系统背后黑盒的核心。
Shell 是指一种应用程序(命令语言),这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
3.进程间的通信方式
每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信
- 管道/匿名管道(Pipes):用于具有亲缘关系的父子进程间或兄弟进程之间的通信。
- 有名管道(Named Pipes):匿名管道,由于没有名字,只能用于亲缘关系的进程间通信。为了克服这个缺点,提出了有名管道。有名管道不同于匿名管道之处在于它提供了一个路径名与之关联,以有名管道的文件形式存在于文件系统中,这样,即使与有名管道的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过有名管道相互通信。
- 信号(Signal):信号是软件层次上对中断机制的一种模拟,是一种异步通信方式,,信号可以在用户空间进程和内核之间直接交互,内核可以利用信号来通知用户空间的进程发生了哪些系统事件,信号事件主要有两个来源:
- 硬件来源:用户按键输入
Ctrl+C
退出、硬件异常如无效的存储访问等。 - 软件终止:终止进程信号、其他进程调用kill函数、软件异常产生信号。
- 硬件来源:用户按键输入
- 消息队列(Message Queuing):消息队列存放在内核中的消息链表。
- 信号量(Semaphores):信号量是一个计数器,用于多进程对共享数据的访问,信号量的意图在于进程间同步。这种通信方式主要用于解决与同步相关的问题并避免竞争条件。
- 共享内存(Shared memory):
- 使得多个进程可以可以直接读写同一块内存空间,是最快的可用进程通信形式。是针对其他通信机制运行效率较低而设计的。
- 为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间。进程就可以直接读写这一块内存而不需要进行数据的拷贝,从而大大提高效率。
- 由于多个进程共享一段内存,因此需要依靠某种同步机制(如信号量)来达到进程间的同步及互斥。
- 套接字(Socket):套接字是一种通信机制,凭借这种机制,客户/服务器(即要进行通信的进程)系统的开发工作既可以在本地单机上进行,也可以跨网络进行。也就是说它可以让不在同一台计算机但通过网络连接计算机上的进程进行通信。
4.线程间的同步方式
线程同步是两个或多个共享关键资源的线程的并发执行。应该同步线程以避免关键的资源使用冲突。操作系统一般有下面三种线程同步方式。
- 互斥量(mutex):采用互斥对象机制,只有拥有互斥对象的线程才有访问资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问。比如Java中的synchronized关键字和各种Lock都是这种机制。
- 信号量(Semphares):多个资源可供访问。
- 事件(Event):Wait/Notify:通过通知操作的方式来保持多线程同步。
5.进程的调度算法
- 时间片轮转:最古老,最简单,最公平且使用最广的算法。每个进程被分配一个时间片。
- 先到先服务:从就绪队列选择队首进程。直到完成或者发生某事件被阻塞放弃占用CPU。
- 短作业优先:从就绪队列中选一个估计运行时间最短的进程为之分配资源。
- 优先级调度:为每个进程分配优先级。相同优先级先来先服务。
- 多级反馈队列调度算法:公认的一种较好的进程调度算法,既照顾高优先级队列,也照顾短作业。
多进程和多线程
同步(synchronous):一定要等任务执行完了,得到结果,才执行下一个任务
异步( asynchronous/non-sequential):不等任务执行完,直接执行下一个任务。
多进程和多线程的主要区别是:1、线程是进程的子集,一个进程可能由多个线程组成;2、多进程的数据是分开的,共享复杂,需要用IPC,但同步简单;3、多线程共享进程数据,共享简单,但同步复杂。
进程是资源分配的最小单位,线程是CPU调度的最小单位。
- 一个进程可包含多个线程,其中有且只有一个主线程。
- 同一程序中的所有线程均会独立执行相同程序。
- 多线程共享同个地址空间、打开的文件以及其他资源。
- 多进程共享物理内存、磁盘、打印机以及其他资源。
进程(process):操作系统为正在运行的程序提供的抽象
线程(thread):是允许应用程序并发执行多个任务的一种机制
线程崩溃到导致进程(或其他线程)崩溃吗?
一般来说,每个线程都是独立执行的单位,每个线程都有自己的上下文堆栈,一个线程的的崩溃不会对其他线程造成影响。但是通常情况下,一个线程崩溃会产生一个进程内的错误,例如在linux操作系统中,可能会产生一个segment fault错误,这个错误会产生一个信号,操作系统默认对这个信号的处理就是关闭进程,整个进程都被销毁了,这样的话这个进程中存在的其他线程自然也就不存在了。
常用的Linux命令
top 显示当前系统中耗费资源最多的进程
kill 杀死一个进程 kill -9 强制杀死
ps 该命令用于将某个时间点的进程运行情况选取下来并输出,process之意,它的常用参数如下
chmod 修改目录或文件的权限
chown 修改文件的所属用户和组
grep 根据文件的内容查找 比如在日志文件中查找某个ip地址
find 根据文件内容查找 比如查找.txt结尾的文件
locate 让使用者可以很快速的搜寻某个路径, 如locate /etc/sh 搜索etc目录下所有以sh开头的文件
wc 统计文本中行数、字数、字符数
touch 创建文件
df -h 显示已经挂载的分区列表
du 一般用于统计文件和目录所占用的空间大小
ifconfig 查看ip,网卡等信息
Linux 常见目录
/ 根目录
/bin 命令保存目录(普通用户就可以读取的命令)
/boot 启动目录,启动相关文件
/dev 设备文件保存目录
/etc 配置文件保存目录
/home 普通用户的家目录
/lib 系统库保存目录
/mnt 系统挂载目录
/media 挂载目录
/root 超级用户的家目录
/tmp 临时目录
/sbin 命令保存目录(超级用户才能使用的目录)
/proc 直接写入内存的
/sys 将内核的一些信息映射,可供应用程序所用
/usr 系统软件资源目录
/usr/bin/ 系统命令(普通用户)
/usr/sbin/ 系统命令(超级用户)
/var 系统相关文档内容
/var/log/ 系统日志位置
/var/spool/mail/ 系统默认邮箱位置
/var/lib/ 默认安装的库文件目录
评论区