Skip to content

Latest commit

 

History

History
159 lines (128 loc) · 10.4 KB

高频问题-操作系统.md

File metadata and controls

159 lines (128 loc) · 10.4 KB

进程与线程的区别

(单位, 包含关系, 创建, 通信, 创建销毁切换成本, 资源)

  • 进程是资源的分配和调度的一个独立单元,而线程是CPU调度的基本单元
  • 同一个进程中可以包括多个线程,并且线程共享整个进程的资源(寄存器、堆栈、上下文),一个进程至少包括一个线程。
  • 进程的创建调用fork或者vfork,而线程的创建调用pthread_create,进程结束后它拥有的所有线程都将销毁,而线程的结束不会影响同个进程中的其他线程的结束
  • 线程是轻量级的进程,它的创建和销毁所需要的时间比进程小很多
  • 线程中执行时一般都要进行同步和互斥,因为他们共享同一进程的所有资源
  • 进程拥有的资源: 虚存空间,对处理器, 进程间通信资源, 文件和IO资源的受保护访问; 线程的资源: 线程状态, 处理器上下文(寄存器和程序计数器),执行栈, 线程本地的存储空间.
  • 线程有自己的私有属性TCB,而进程也有自己的私有属性进程控制块PCB,这些私有属性是不被共享的,用来标示一个进程或一个线程的标志

进程调度算法的特点以及使用场景

(FCFS, RR, 总时间最短, 剩余时间最短, 响应性最高, 多级反馈)

进程调度算法首先分为两种: 抢占式和非抢占式

  • 抢占式: 当一个进程占用处理器时, 可以被中断
  • 非抢占式: 一旦选择了一个进程使用处理器, 只能等到其主动释放处理器.

进程调度算法比较

进程通信方法的特点以及使用场景IPC

(5种)

  • 信号: 传递的信息少, 通常是一个通知, 由被调用进程注册signal处理函数对其处理
  • 管道: 依赖父进程, 将上一个进程的输出作为下一个进程的输入, unix中管道以文件的形式存在,会产生读写阻塞.
  • 消息队列: 不依赖父进程可以在多个独立的进程时间传递信息, 更加结构化消息.
  • 共享内存: 速度最快, 通过地址空间的映射实现, 需要应用程序自己控制同步问题.
  • socket

死锁

  • 死锁概念: 进程之间相互等待对方占有的资源而无法运行的情况
  • 饥饿概念: 由于资源分配策略不公平导致某些进程持续得不到资源或不能执行
  • 死锁产生条件: 资源独占 不可剥夺 持续申请 循环等待(前三个是必要条件)
  • 解决死锁的策略
    • 死锁预防: 按一定的顺序获取锁打破循环等待
    • 死锁避免: 银行家算法
    • 死锁检测: Aloc + available的算法
    • 死锁恢复:

死锁的代码:

class DeadLock implements Runnable {
    private String lock1, lock2;
    public DeadLock(String lock1, String lock2) {
        this.lock1 = lock1;
        this.lock2 = lock2;
    }
    public void run() {
        synchronized(lock1) {
            System.out.println(Thread.currentThread().getName() + " obtain " + lock1);
            try {
                Thread.sleep(200);
                synchronized(lock2) {
                    System.out.println(Thread.currentThread().getName() + " obtain " + lock2);
                }
            }
            catch (InteruptionException e) {

            }
        }
    }
}

public class DeadLockSample {
    public static void main(String[] args) {
        String s1 = "lock1";
        String s2 = "lock2";
        new Thread(new DeadLock(s1, s2)).start();
        new Thread(new DeadLock(s2, s1)).start();
    }
}

上述代码大概率可以出现死锁的情况, 可以使用jstack工具进入当前的JVM进程查看线程的情况, 来分析是否有死锁, 重点的查看block的线程的锁占用情况.

银行家算法的实现:

// todo

Java和数据库中防止死锁的基本方法是保证加锁的顺序一致.

数据库中用for update?

Java线程的6种状态

  1. 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。
  2. 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。 线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。
  3. 阻塞(BLOCKED):表示线程阻塞于锁。
  4. 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
  5. 超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。
  6. 终止(TERMINATED):表示该线程已经执行完毕。

虚拟内存的作用,分页系统实现虚拟内存原理

(局部性原理 2条, 虚存作用 2条, 虚存地址查找实际页面的过程)

虚拟内存的基础是局部性原理

  • 时间局部性, 如果一个数据正在被访问, 它最近还可能被访问
  • 空间局部性, 如果一个数据正在被访问, 它临近的数据最近也可能被访问

虚拟内存的作用

  • 应用程序的大小不受物理内存大小的限制, 与物理内存大小解耦, 程序员不需要考虑内存的overlay
  • 程序不需要完全装入内存就可以运行, 有更多进程可以进入内存, 提高处理器的吞吐率

分页是系统的虚存实现原理

  • 逻辑地址: 程序在编译时地址使用的是逻辑地址, 逻辑地址可以看做是页号+偏移量
  • 进程运行时当需要访问一个逻辑地址时, 首先按照页号去进程的页表查找页框号, 如果当前页在内存中, 则得到页框号+偏移量获得物理地址; 如果当前页不在内存中, 则报缺页中断,进程被阻塞由OS负责将当前页从磁盘中加载到内存, 这个过程还需要考虑页面置换
  • 由于虚拟内存的大小例如32位地址4k的页面大小, 则页号空间为2^20, 因此需要采用多级页表, 页表的管理也按照虚存进行管理, 如果每次访问一个虚存都需要查找页表则会导致性能的下降, 因此引入了TLB(转换检测缓冲区), 首先在TLB中查找页框号, 如果没有再去页表中查找.

页面置换算法的原理

(4种)

  • OPT: 未来最长时间不会用到的页, 不可能实现
  • LRU: 内存中最久没有访问的页, 硬件实现难度大
  • FIFO: 最早加载的也可能是频繁访问的, 频繁切换
  • 时钟: 设置访问位;记录上一次检查到这一次之间是否被访问过, 如果访问过,就暂时不替换, 但是把访问位置为0; 如果所有的页访问位都为1, 转一圈全部置为0后, 遇到的第一个0的页面置换出去

比较分页与分段的区别

(可见性, 大小, 碎片)

  • 段是信息的逻辑单位,它是根据用户的需要划分的,因此段对用户是可见的 ;页是信息的物理单位,是为了管理主存的方便而划分的,对用户是透明的。
  • 段的大小不固定,有它所完成的功能决定;页大大小固定,由系统决定
  • 段向用户提供二维地址空间;页向用户提供的是一维地址空间
  • 段是信息的逻辑单位,便于存储保护和信息的共享,页的保护和共享受到限制。

分析静态链接的不足,以及动态链接的特点

静态链接的不足:

  • 可执行文件增大
  • 一旦库被修改整个文件需要重新编译
  • 不能共享代码

linux中僵尸进程与孤儿进程的区别

僵尸进程是等待父进程通过wait方法回收的进程, 而孤儿进程是自己进程结束以前父进程就已经结束了, 孤儿进程依赖root进行回收.

linux中硬链接与软链接的区别

(创建是否需要存在, 元数据是否相同, 删除的影响, 是否可以链接目录)

linux中, 文件包括3个部分, 文件名, innode, block. 文件名和innode是保存在目录的一条目录项中的, 而block是文件数据的存放位置, innode中记录了文件的元数据.

linux中使用对一个文件使用硬链接是对同一个inode的增加了不同文件路径名, 而对一个文件使用软连接则是创建了一个普通文件, 文件的用户数据块的内容是被链接的文件的路径. 二者的区别:

  • 硬链接依赖inode, 因此只有文件存在时才可以创建; 软链接就是创建了一个普通文件, 因此可以对并不实际存在的路径创建.
  • 硬链接关联的文件具有相同的元数据, 因为它们的inode只有一个; 软链接关联的两个文件的元数据可以不同, 因此可以具有不同的权限
  • 删除创建硬链接会修改inode使得硬链接计数改变, 修改软链接不会修改源文件的inode.
  • 硬链接不能链接目录, 因为当前目录和父目录两个文件的实现就是硬链接,随意的链接目录会造成目录环; 软链接可以链接目录.