1.进程与线程
进程(Process):系统进行资源分配和调度的基本单位,一个进程并发多个线程,每个线程执行不同的任务
线程(Thread):操作系统运行调度的最小单位,包含在进程中,是进程中实际运行的工作单位
进程中的多个线程共享进程资源(所以多线程也需要同步)
进程与线程区别:
进程 | 线程 | |
---|---|---|
资源 | 资源分配的基本单位 | 不拥有独立资源 |
调度 | 独立调度的基本单位 | 独立调度的最小单位 |
系统开销 | 开销大 | 开销小 |
通信 | 进程IPC | 读写统一进程数据通信 |
进程五状态:创建、就绪、执行、阻塞、终止
2.进程的调度
进程的调度是指计算机通过决策决定哪个就绪进程可以获得CPU使用权
调度的三机制
-
就绪队列排队
-
选择运行进程委派
-
新老进程上下文切换
3.调度算法
-
先来先服务
-
短进程优先
-
高优先权有限(紧迫任务)
-
时间片轮转(相对公平)
- 按先来先服务排列就绪进程
- 头部去除,分配一个时间片(时间片结束,无论是否执行完,进行下一个进程,若没有执行完毕插入队尾)
4.死锁
产生原因:
- 竞争资源
- 进程调度顺序不当
产生条件:
- 互斥:
- 进程对资源的使用有排他性
- 某资源只能有一个进程使用,其他进程需要等待
- 请求保持
- 进程至少保持一个资源,同时又提出新的请求
- 新资源被占用,请求被阻塞
- 被阻塞的进程不释放自己保持的资源
- 不可剥夺
- 进程获得的资源未完成前不能被剥夺
- 资源只能由进程自身释放
- 环路等待
5.分页与分段的区别
- 分页对程序员透明,分段需要程序员显示划分每个段
- 分页是一维地址空间,分段是二维
- 页大小由硬件固定,段长度可动态变化
- 分页主要用于实现虚拟内存,从而获得更大的地址空间,而分段主要为了使程序和数据可以被划分为逻辑上独立的地址空间并且有助于共享和保护
6.虚拟内存
使用原因:
- 进程需要实际内存太大,超过物理内存容量
- 多道程序设计,每个进程可用物理内存稀缺
- 不可能无限增加物理内存
作用:
- 是操作系统内存管理的关键技术
- 使多道程序和大程序运行
- 是对物理内存的补充,速度接近于内存
7.置换算法
在程序运行过程中,如果要访问的页面不在内存中,就发生缺页中断从而将该页调入内存中。此时如果内存已无空闲空间,系统必须从内存中调出一个页面到磁盘对换区中来腾出空间。
页面置换算法的主要目标是使页面置换频率最低(也可以说缺页率最低)。
Node节点类:
/**
* 链表节点类
* @author falcon
*
*/
class Node {
public int key;
public int value;
public Node pre;
public Node next;
/**
* 节点初始化
* @param key
* @param value
*/
public Node(int key, int value) {
this.key = key;
this.value = value;
this.pre = null;
this.next = null;
}
@Override
public String toString() {
return "{" + key + "," + value + "}";
}
}
双向链表类:(包含测试)
public class DoubleLinkedList {
public Node node;
public int capacity;// 容量
public Node head;// 双向链表头指针
public Node tail;// 双向链表尾指针
public int size;// 当前链表存储节点个数
public DoubleLinkedList() {
this.capacity = 0xffff;
this.head = null;
this.tail = null;
this.size = 0;
}
public DoubleLinkedList(int capacity) {
this.capacity = capacity;
this.head = null;
this.tail = null;
this.size = 0;
}
/**
* 往头部增加节点
* @param node
* @return
*/
public Node add_head(Node node) {
if (size == 0 || this.head == null) {
this.head = node;
this.tail = node;
this.head.pre = null;
this.head.next = null;
} else {
node.next = this.head;// 把增加节点的下一个节点的引用指向head节点的引用
this.head.pre = node;// 把head节点的上一个引用指向增加的节点
this.head = node;// 把头指针指向增加的节点
}
this.size++;
return node;
}
/**
* 往尾部增加节点
* @param node
* @return
*/
public Node add_tail(Node node) {
if (size == 0 || this.tail == null) {
this.tail = node;
this.head = node;
this.tail.next = null;
this.tail.pre = null;
} else {
this.tail.next = node;
node.pre = this.tail;
this.tail = node;
}
this.size++;
return node;
}
/**
* 删除头部节点
* @return
*/
public Node remove_head() {
if (this.head == null) {
return null;
}
node = this.head;
if (node.next != null) {
this.head = node.next;
this.head.pre = null;
} else {
this.head = this.tail = null;
}
size--;
return node;
}
/**
* 删除尾部节点
* @return
*/
public Node remove_tail() {
if (this.tail == null) {
return null;
}
node = this.tail;
if (node.pre != null) {
this.head = node.pre;
this.head.next = null;
} else {
this.head = this.tail = null;
}
size--;
return node;
}
/**
* 删除任意节点
* @param node
* @return
*/
public Node remove(Node node) {
// 如果node为空 默认删除尾部节点
if (node == null) {
node = this.tail;
}
if (node == this.tail) {
this.remove_tail();
return node;
} else if (node == this.head) {
this.remove_head();
return node;
} else {
node.pre.next = node.next;
node.next.pre = node.pre;
}
this.size--;
return node;
}
// 弹出头部节点
public Node pop() {
return this.remove_head();
}
// 添加节点
public Node append(Node node) {
return this.add_tail(node);
}
// 往头部添加节点
public Node append_front(Node node) {
return this.add_head(node);
}
// 删除节点
public Node removeNode() {
return this.remove(node);
}
public void print() {
Node p = this.head;
String msg = "";
while (p != null) {
msg += p;
p = p.next;
if (p != null) {
msg += "=>";
}
}
System.out.println(msg);
}
public static void main(String[] args) {
DoubleLinkedList dll = new DoubleLinkedList();
Node[] nodes = new Node[10];
for (int i = 0; i < 10; i++) {
Node node = new Node(i, i);
nodes[i] = node;
}
dll.append(nodes[0]);
dll.print();
dll.append(nodes[1]);
dll.print();
dll.pop();
dll.print();
dll.append(nodes[2]);
dll.print();
dll.append_front(nodes[3]);
dll.print();
dll.append(nodes[4]);
dll.print();
dll.remove(nodes[2]);
dll.print();
}
}
-
先进先出(FIFO)
/** * 缓存置换算法FIFO * 先进先出 * @author falcon */ public class FIFOCache { public Node node; public int capacity; public int size; public Map<Integer,Node> map ; public DoubleLinkedList list; public FIFOCache(int capacity) { this.capacity = capacity; this.size = 0; this.map = new HashMap<Integer,Node>(); this.list = new DoubleLinkedList(capacity); } public int get(Integer key) { if(this.map.get(key)==null) { return -1; }else { node = this.map.get(key); return node.value; } } public void put(Integer key,int value) { if(capacity == 0) { return ; } if(this.map.containsKey(key)){ node = new Node(key,value); this.list.remove(this.map.get(key)); this.list.append(node); }else { if(this.size==this.capacity) { node = this.list.pop(); this.map.remove(node.key); size--; } node = new Node(key,value); this.list.append(node); this.map.put(key, node); } size++; } public void print() { this.list.print(); } //测试 public static void main(String[] args) { FIFOCache cache = new FIFOCache(2); cache.put(1, 1); cache.print(); cache.put(2, 2); cache.print(); System.out.println(cache.get(1)); cache.put(3, 3); cache.print(); System.out.println(cache.get(2)); cache.put(4, 4); cache.print(); System.out.println(cache.get(1)); System.out.println("-----------"); System.out.println(cache.size + "--" + cache.list.size); } }
-
最不经常使用(LFU)
-
最近最少使用算法(LRU)
/** * 最近最少使用算法 * @author falcon * */ public class LRUCache { public Node node; public int capacity; public Map<Integer,Node> map ; public DoubleLinkedList list; public LRUCache(int capacity) { this.capacity = capacity; this.map = new HashMap<Integer,Node>(); this.list = new DoubleLinkedList(capacity); } public int get(Integer key) { if(this.map.get(key)==null) { return -1; }else { node = this.map.get(key); this.list.remove(node); this.list.append_front(node); return node.value; } } public void put(Integer key,int value) { if(capacity==0) { return ; } //如果包含 放到list最前面 if(this.map.containsKey(key)) { node = this.map.get(key); this.list.remove(node); node.value = value; this.list.append_front(node); }else {//如果不包含,则需要添加 node = new Node(key,value); //如果容器满了 if(this.list.size>=this.capacity) { Node remove_tail = this.list.remove(null); this.map.remove(remove_tail.key); } //容器没满 this.map.put(key, node); this.list.append_front(node); } } public void print() { this.list.print(); } public static void main(String[] args) { LRUCache cache = new LRUCache(2); cache.put(1, 1); cache.print(); cache.put(2, 2); cache.print(); System.out.println(cache.get(1)); cache.print(); } }
参考资料
- CyC2018/CS-Notes.
- 慕课网计算机操作系统