alin的学习之路: 面试题 操作系统相关

alin的学习之路: 面试题 操作系统相关

  • 进程与线程的区别

    • 进程是资源分配的最小单位,线程是程序执行的最小单位。

    • 进程有自己独立的地址空间,线程共享地址空间

    • 进程:无名管道、有名管道、信号、共享内存、消息队列
      线程:互斥量、读写锁、自旋锁、线程信号、条件变量、信号量

    • 线程有四种状态:1.新生状态 2.可运行状态 3. 被阻塞状态 4.死亡状态

  • 多进程与多线程区别,应用场景

    • 多进程要使用fork()函数进行创建,多线程要使用pthread_create()函数进行创建

    • 开销方面:每个进程都有独立的代码和数据空间(程序上下文),进程之间切换开销大;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。

    • 所处环境:在操作系统中能同时运行多个进程(程序);而在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行)

    • 内存分配:系统为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源

    • 包含关系:线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程

  • volatile和原子变量的区别

  • proc文件系统

  • 自旋锁与普通锁的区别

    1.读写锁: 有三个状态:读加锁状态、写加锁状态、不加锁状态。
    读写锁可以支持高并发,其中一个原因就是 只能允许一个线程占用写状态锁,但是多个线程可以共享读状态锁。当写状态锁被占用的时候,后续想要写状态的线程就会被阻塞。所以读写锁非常适合那些 读状态 远远多于 写状态的应用场景。
    特点
    1.多个读线程可以同时进行读
    2.写线程必须互斥,不能同时读同时写。
    3.写线程优先于读线程,先写加锁线程之后才能读加锁线程。
    2.互斥锁:访问共享资源时,允许一个线程对资源区进行操作,其他线程即为堵塞睡眠状态,直到被唤醒。
    特点:一次只能一个线程拥有互斥锁,其他线程只有等待。
    3.自旋锁
    自旋锁是一种特殊的互斥锁,当资源被加锁后,其他想要访问的线程不会被阻塞而是陷入循环等待状态,循环检查资源持有者是否已经释放了资源,这样的好处是节省了线程从休眠到被唤醒的开销,但同时也会一直占据CPU的资源。所以自旋锁适合多核CPU、共享资源区被加锁的时间短的情况。但是还有一个问题是当自旋锁递归调用的时候会造成死锁现象。所以慎重使用自旋锁。
    4.乐观锁、悲观锁:一种思想:当线程去访问数据的时候,如果认为其他线程 不会修改数据,那么就不会对数据资源上锁,但是在更新数据的时候会去判断以下其他线程是否修改了数据。通过版本来判断,如果数据被修改了就拒绝更新,这就是乐观锁,即不上锁。悲观锁反之,它会对数据加锁,保证数据的正确性。
    特点:以上两种锁多用于数据库,当读操作远远大于写操作的时候,乐观锁的效率会很高,会增加数据库的吞吐量。

  • 虚拟内存

    • mmap 将一个文件映射到进程的虚拟地址空间,实现了文件磁盘地址与进程虚拟地址的一一对应关系,实现这样的关系之后,进程就可以通过指针的方式去读写这一段内存,避免了通过write/read 函数,(write/read函数会形成多次拷贝,内核压力过大)。相反,内也可以通过映射直接修改数据,从而实现不同进程之间对该内存空间的通信,这也就是进程之间共享内存的通信方式。
    • mmap 优势:
      1. 对文件的读取跨过了页缓存,减少了数据的拷贝次数,提高了文件的读取效率
      2. 共享内存通信方式提供了一种不管什么进程都可以通信的方式,父子进程等都可以。
  • 进程的内存分布

    • 在这里插入图片描述

  • 栈内存为什么由系统自动分配和释放

    • 栈内存空间一般较小,在程序中的局部变量和全局变量声明是直接由系统赋予内存空间,但是当某些变量所需内存空间较大,则有程序员手动申请和释放空间,而这些空间一般为堆内存。
  • 守护进程如何创建

    1. 创建子进程,父进程退出(必须)
      • 所有工作在子进程中进行形式上脱离了控制终端
    2. 在子进程中创建新会话(必须)
      • setsid()函数
      • 使子进程完全独立出来,脱离控制
    3. 改变当前目录为根目录(不是必须)
      • chdir()函数
      • 防止占用可卸载的文件系统
      • 也可以换成其它路径
    4. 重设文件权限掩码(不是必须)
      • umask()函数
      • 防止继承的文件创建屏蔽字拒绝某些权限
      • 增加守护进程灵活性
    5. 关闭文件描述符(不是必须)
      • 继承的打开文件不会用到,浪费系统资源,无法卸载
    6. 开始执行守护进程核心工作(必须)

    守护进程退出处理程序模型

  • 进程间的通信方式及其区别,应用场景

    • 匿名管道pipe:使用简单,父子进程间的简单通信可以使用。

    • 命名管道fifo:使用fifo文件,可以在不相干的两个进程之间进行通信。

    • 消息队列:消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。

    • 信号signal:传递的信息少。

    • 共享存储映射mmap:通信的数据映射到磁盘文件中,可以反复使用。

    • 套接字socket:多用于网络通信。分为本地套接字和网络套接字。

    • 共享内存:通过多个进程共享同一块内存中的数据从而达到通信的目的,是速度最快的通信方式,需要配合信号量机制实现进程同步。
      共享内存的缺点:基于内存,只能在同一主机内使用,不能应用与分布式系统当中。

  • 死锁条件和解除

    • 死锁:死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
      原理:当一组进程或者线程都在等待某个事件的产生,而且只有该组进程/线程才能出发该事件,这就称这组进程、线程发生了死锁。

      死锁产生的四个必要条件:
      1.互斥,某种资源只允许一个进程访问,另一个进程想要访问该资源必须等待阻塞。
      2.占有并等待,当某个进程本身占有资源,同时它又在等待其他线程释放的某种其他的资源,这就造成了这两个线程出现相互等待的现象。
      3.不可抢占,产生第2条的条件之一就是两个进程之间不可抢占被别人占据的资源,也即是互斥条件
      4.循环等待,存在一个进程链,使得每一个进程都占有下一个进程所需要的至少一种资源

    • 处理死锁的思路

      • 预防死锁

        破坏死锁的四个必要条件中的一个或多个来预防死锁。

      • 避免死锁

        和预防死锁的区别就是,在资源动态分配过程中,用某种方式防止系统进入不安全的状态。

      • 检测死锁

        运行时出现死锁,能及时发现死锁,把程序解脱出来

      • 解除死锁

        发生死锁后,解脱进程,通常撤销进程,回收资源,再分配给正处于阻塞状态的进程。

    • 预防死锁的方法

      • 破坏请求和保持条件

      • 破坏不可抢占条件

      • 破坏循环等待条件

  • 进程调度方式

    • 先来先服务算法:FCFS ,按照顺序执行

    • 短作业优先算法:SJF 按照任务时间,先执行时间短的

    • 最高响应比优先法:以上两种的综合算法,提高效率

    • 时间片轮转法:采用剥夺方式,每个进程分配一个固定的时间段,按照队列中的顺序执行

    • 多级反馈队列:UNIX采用这种算法。算

  • 对编译连接的理解

    • 编译是从源文件检查语法错误并生成汇编文件的过程。

    • 连接:寻找需要使用的库的代码并连接,并且为程序生成一个启动代码。

  • 共享内存实现原理

    • 共享内存可以说是最有用的进程之间的通信方式,两个进程之间的共享内存的意思是,同一块的物理内存被映射到进程A/B各自的进程地址空间,A/B都可以随时看到共享内存中数据的更新。
      Linux中,通过吧一块内存分别映射到不同的进程空间中实现进程间通信,实际中需要联合同步、互斥机制来一起完成。

    • 共享内存实现机制
      一、mmap机制:在磁盘上建立一个文件,每个进程存储器中,单独开辟一个空间来映射
      保存到实际硬盘,实际并没有反映到主存上
      优点:存储量大
      缺点:读取和写入速度比较慢
      mmap() 是一个系统调用函数,本质是一种进程虚拟内存的映射方法,可以将一个文件、一段物理内存或者其它对象映射到进程的虚拟内存地址空间。实现这样的映射关系后,进程就可以采用指针的方式来读写操作这一段内存,进而完成对文件的操作,而不必再调用 read/write 等系统调用函数了。

    • 常规的文件操作为了提高读写效率和保护磁盘,使用了页缓存机制。这样造成读文件时需要先将文件页从磁盘拷贝到页缓存中,由于页缓存处在内核空间,不能被用户进程直接寻址,所以还需要将页缓存中数据页再次拷贝到内存对应的用户空间中。这样,通过了两次数据拷贝过程,才能完成进程对文件内容的获取任务。写操作也是一样,待写入的 Buffer 在内核空间不能直接访问,必须要先拷贝至内核空间对应的主存,再写回磁盘中(延迟写回),也是需要两次数据拷贝。
      共享内存通过零拷贝技术,直接将磁盘文件拷贝到内核缓存中,然后进程通过共享内存直接读取,整个过程只有一次拷贝,所以从效率上来说是比传统读写高的。

    • 二、shm机制:每个进程的共享内存都直接映射到实际物理存储器上
      shm保存到物理存储器(主存),实际的存储量直接反映到主存上
      优点:进程间访问速度比磁盘快
      缺点:存储量不能非常大

  • 僵尸进程是什么,如何处理

    • 子进程先于父进程结束,父进程还没有结束后的自动回收子进程,并且父进程没有手动对子进程进行回收,此时该子进程被称为僵尸进程。
    • 处理方法:注册一个SIGCHLD信号处理函数,当收到SIGCHLD信号时说明子进程的状态发生了改变,通常是子进程结束,此时执行waitpid()回到掉子进程即可。
  • 自旋锁在单cpu与多cpu下的使用

    • Linux上的自旋锁有三种实现:

      1. 在单cpu,不可抢占内核中,自旋锁为空操作。
      2. 在单cpu,可抢占内核中,自旋锁实现为“禁止内核抢占”,并不实现“自旋”。
      3. 在多cpu,可抢占内核中,自旋锁实现为“禁止内核抢占” + “自旋”。
    • 自旋锁在单核处理器中容易造成CPU的瘫痪

  • 用户态与内核态

    • 用户态是在用户内存空间,内核态是在内核的内存空间

    • 在这里插入图片描述

    • 3G-4G大部分是共享的,是内核态的地址空间。这里存放整个内核的代码和所有的内核模块以及内核所维护的数据。
      计算机系统中通常运行两种程序,一种是系统程序,一种是应用程序。
      即用户态和内核态,但是在程序运行通常会在这两种状态中切换。为了区分操作级别,X86 cpu架构采用了 0 - 3 四种特权阶级,其中 0 级为最高特权。
      特权指令:对内存空间的访问范围基本不受限制,不仅能访问用户存储空间,也能访问系统存储空间,特权指令只允许操作系统使用,不允许应用程序使用,否则会引起系统混乱。
      非特权指令:一般应用程序所使用的都是非特权指令,它只能完成一般性的操作和任务,不能对系统中的硬件和软件直接进行访问,其对内存的访问范围也局限于用户空间。

    • 用户态切换到内核态的唯一途径——>中断/异常/陷入
      内核态切换到用户态的途径——>设置程序状态字

      当进行I/O操作的时候,由内核态到用户态的拷贝转移是极其耗费 cpu 资源的,零拷贝是追求的目标。

  • Linux 的文件存储系统

    1. 最小单位是扇区,每个扇区512字节,
    2. 按块读取,每个块有八个扇区,即 4Kb,
    3. inode 即索引节点,其中包含了文件的大小,创建等基本信息
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值