操作系统一遍过

 写一点OS的基础知识,面试中持续更新...

基基础知识

1.计算机硬件:输入/输出设备,存储器,运算器,控制器。

2.三种基本OS类型

批处理OS:单道批处理(CPU利用率低),多道批处理(缺乏交互性)

分时OS:时间片轮转分配;

实时OS:及时响应,高可靠性

3.最基本特征:并发和共享

4. 并行与并发:并行:真正意义上的同时执行,而并发还是一个接一个的执行,在一段时间内得到时间片轮转进行执行,一段时间后执行完毕,宏观上并行。


进程&线程相关

1. 概念:程序在一个数据集合上的一次运行过程,是OS资源分配的基本单位;

2. 动态、并发、独立、异步,一个程序可以包含多个进程;

3. 组成:程序、数据、PCB(标识符、状态-阻塞、就绪、执行)、优先级、CPU现场保护区、家族联系(父子自之间的关系)、占有资源的清单

4. 状态:就绪阻塞和执行,三个队列。当就绪状态发生进程调度是,进入执行状态,执行状态请求资源(比如IO操作)无法满足是发生阻塞,被丢入阻塞队列,当资源被满足时完成功能后进入就绪状态;

 

5. 核心态和用户态:核心态拥有搞特权,可以执行所有指令,访问所有寄存器和存储区;用户态低特权,只能访问部分存储区,执行部分指令。

6.创建:一般使用fork()函数创建子进程,要注意僵尸进程的出现,如何解决?在UNP中有说明:使用信号函数signal捕获SIGCHLD信号,使用相应函数处理(使用waitpid)。

7.线程:OS进行调度的基本单位,同意进程内的所有县城共享进程的内存空间(资源),他们只拥有自己的程序计数器、栈和少量寄存器。

8. 创建:pthread_create(tid, 函数,参数)

9. 回收:其他线程使用pthread_join()来回收,或者在线程函数中设置线程脱离pthread_detach()使得执行完函数之后自行结束;

进程线程的不同:

  9.1. 调度的基本单位和资源分配的基本单位;

  9.2. 是否拥有资源:进程拥有,线程只拥有少量寄存器和程序计数器还有栈;

  9.3. 开销:创建开销,进程要涉及分配内存空间,所以要比线程慢,撤销也类似;特别的切换开销,进程的现场保护要比线程复杂,进程要切换内存空间,然后切换栈和相关寄存 器,而线程只需要后面的步骤,不需要切换内存空间,所以快。(UNP说线程创建可能要比进程快10~100倍)。

  9.4. 通信:进程间由于内存空间隔离,所以要跨内存空间来通信(使用管道,消息队列,共享内存,信号量,socket套接字),而线程通过全局便来个就可进进行通信。

  9.5.适用场景:多线程适用于多机,而多线程适用于多核;

10.进程间通信(IPC)

管道:匿名管道和命名管道,匿名管道只能用于具有亲缘关系的进程之间,而命名管道可以用于一般的进程之间;Linux头文件<pipe.h>

消息队列:创建消息队列,一个进程去读,另一个去写;头文件:<mqueue.h>,mq_open()和mq_clos();

共享内存:最快的一种IPC方式,为什么快?因为他直接将进程的进程空间映射到要使用的内存空间中,这样就避免了其他方式中的与内核缓冲区交互的时间开销。(其他的方式一般都是将设局写入进程缓冲区,而后进入内核缓冲区,然后另一个进程再从内核缓冲区中将数据读到自己的进程缓冲区中)<sys/mman.h>

socket:一种可以实现远端进程通信的一种方式。Linux头文件<sys/socket.h>

(TCP/UDP各有编程范式)

11.进程同步:

互斥锁:pthread_mutex_t,pthread_mutex_lock/trylock/unlock

读写锁:读锁和写锁,读锁共享,写锁互斥。和数据库的读写锁类似。

信号量:<semaphore.h>sem_open()/wait/trywait(),实例就是操作系统都做过的生产者消费者这问题

条件变量:pthread_cond_t signal()和wait()函数,通常和互斥量一起使用。

记录锁:对记录上锁,典型例子时文件锁。

12. 作业调度算法

  12.1 先来先服务FCFS:就是先来的(在就绪队列头部的)先调度执行,后面的统统等着。(这让我想起了今早上宿舍中一舍友上厕所上了半个小时...我也很急,但又不能抢占资源...无奈的我只得寻找另一台主机,成为他的一个临时进程)

  12.2 短作业优先SJF:就是短的先执行。对长作业非常不友好,导致长作业“饥饿”。

  12.3 优先级调度PSA:为作业确定优先级,从后备队列中选取优先级高的装入内存。

  12.4 高响应比优先:每次选取响应比较高的作业装入内存(响应比:(等待时间+运行时间)/等待时间),这种算法考虑了等待时间的因素。

13. 死锁

一组进程队列中,每个进程都等待其他进程所持有的资源,造成循环等待的局面。

4个条件:互斥条件、请求与保持、不可剥夺、环路条件

如何预防:从234条件下手,请求需要先释放、可以高优先级剥夺、为每一类资源进行编号,请求高的需要先释放低的。

如何避免:银行家算法,搞清需求,进行预分配,判断是否能找到一个安全状态。

如何检测:资源分配图能否完全化简;

如何解决:1.终止进程(全部终止;按照次序终止,直到死锁状态解除);2. 付出代价最小的解除算法()

14. 虚拟存储器

 在我看来,虚拟存储器并未从实际上扩充物理内存。而是通过换页技术“看起来像是”扩充了物理内存。用到的原理涉及时间局部性和空间局部性。

在运行初始,只把必要的程序装入内存页,运行时如果发生缺页再进行缺页置换,置换的算法著名的有LRU(最近最少使用算法),原理是使用过的程序和数据,很有可能会在一段时间后继续访问。

这样就可以将一个非常大的软件或程序运行起来,只不过是换页技术在其作用而已。

15. 物理内存与虚拟内存

 物理内存对应于物理地址,虚拟内存对应于逻辑地址,它们之间存在一个映射关系。

1. CPU访问一个逻辑地址时,需要将逻辑地址分解成为一个组号和组内地址;根据组号去查地址转换表,确定该组信息是否在内存中;

2. 如果该组号已经在内存(主存)中,那么从地址转换表中读出对应的物理组号;并根据物理组号和组内逻辑地址,存取必要的信息;

3. 如果该组号不在内存中,那么发生缺页中断,需要将存储在磁盘(辅存)上的信息读入内存中,如果有空闲页,直接读入,否则需要选定页置换出内存,再把需要的信息换入内存中,并更新地址转换表。

缺页置换的算法

1.随机算法:生成一个随机数,来确定将那一页换出内存;

2.先进先出算法:将最先进入的页换出;

3.最近最少使用算法:替换最近最不常使用的页;LRU

4.最优算法:替换最长时间以后才使用的页面(一个理想算法)。

16。程序编译的过程

17.静态链接和动态链接的比较

1. 静态链接库需要装配入可执行文件中,而动态链接库不需要;

2. 静态链接库函数直接在可执行文件中你,所以执行速度快;而动态链接库,则是需要临时去库中寻找,所以执行速度稍慢;

3. 静态链接导致可执行文件臃肿,而使用动态链接库的可执行文件清爽,节约存储空间;

4. 此外静态链接库还存在重复装配的问题(#ifndef之流就是来解决他这类问题的),动态链接库不存在此问题;

5. 静态链接库更新和扩展麻烦(已经链接入可执行文件了),需要重新编译软件,而使用动态链接库,只需要替换动态链接库文件即可。

(图源Baidu)

猜你喜欢

转载自www.cnblogs.com/yocichen/p/11406218.html