石器时代 —— 操作系统面试题

“进程” or “线程”

  • 进程:具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位
  • 线程:进程的一个执行单元,是CPU调度和分派的基本单位,也被称为称为轻量级进程
  • 关联
  • 一个进程可以由多个线程或单个线程组成
  • 线程与同属一个进程的其他的线程共享进程所拥有的全部资源
  • 二者均可并发执行
  • 区别
  • 地址空间:进程拥有独立的地址空间; 线程共享本进程的地址空间。
  • 资源拥有: 进程是拥有系统资源的一个独立单位,而线程自己基本上不拥有
  • 系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),和其他线程共享本进程的相关资源如内存、I/O、cpu等。
  • 独立性: 一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。
  • 系统开销:在进程切换时,涉及到整个当前进程CPU环境的保存环境的设置以及新被调度运行的CPU环境的设置,而线程切换只需保存和设置少量的寄存器的内容,并不涉及存储器管理方面的操作,可见,进程切换的开销也远大于线程切换的开销。
  • 执行过程: 每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制

进程之间的通信 IPC

  • 进程间通信(IPC,InterProcess Communication)是指在不同进程之间传播或交换信息。
  • 常用方式
    • 管道(包括无名管道和命名管道):既可在程序中使用,也可在shell中使用,管道是一种半双工的通信方式,数据只能单向流动。管道的问题在于他们没有名字,只能在具有亲缘关系(父子进程间)的进程间使用。当需要一个双向数据流时,我们必须创建两个管道,每个方向一个。这也就是全双工管道的实现原理:由两个半双工管道构成。
    • 命名管道 (named pipe) :即FIFO,命名管道也是半双工的通信方式。提供单向数据流。克服了管道没有名字的限制,因此允许无亲缘关系的进程间通信,解决了管道的上述问题。管道和FIFO都是使用通常的read和write函数访问。FIFO由mkfifo函数创建。FIFO不同于管道的是,每个FIFO有一个路径名与之关联,从而允许无亲缘关系的进程访问同一FIFO。FIFO的真正优势表现在服务器可以是一个长期运行的进程(如守护进程),而且与其客户可以无亲缘关系。
    • 消息队列message queue:消息队列是消息的链表,包括Posix消息队列systemV消息队列。有足够权限的进程都可以向队列中添加消息,有足够读权限的进程都可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
    • 信号量semophore:主要作为进程间以及同一进程内不同线程之间的同步手段。进程间通信处理同步互斥的机制。信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。
    • 信号signal: 是一种处理异步事件的方式。信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。除了用于进程外,还可以发送信号给进程本身。信号和信号量是不同的,他们虽然都可用来实现同步和互斥,但前者是使用信号处理器来进行的,后者是使用P,V操作来实现的。
    • 共享内存shared memory:是由一个进程创建,但多个进程都可以访问的同一块内存空间。是最快的可用IPC形式(因为共享内存区中的单个数据副本对于共享该内存的所有线程或进程都是可用的)。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同
      步和通信。
    • 套接字socket:更为一般的进程间通信机制,可用于不同机器之间的进程间通信。
    • 远程过程调用:RPC等。其中 套接字( socket )和远程过程调用:RPC支持不同主机上的两个进程IPC。构筑一个应用程序时,如果所有进程都在同一台主机,那么可以使用前面的各种IPC方式;如果进程不在同一个主机上,那就要求进程间使用某种形式的网络通信,RPC提供了这样一种工具,它属于隐式网络编程的范畴。

进程状态

  • 就绪状态:进程已获得除处理机以外的所需资源,等待分配处理机资源
  • 运行状态:占用处理机资源运行,处于此状态的进程数小于等于CPU数
  • 阻塞状态: 进程等待某种条件,在条件满足之前无法执行

线程共享的数据

  • 进程代码段
  • 进程的公有数据(利用这些共享的数据,线程很容易的实现相互之间的通讯)、
  • 进程打开的文件描述符
  • 信号的处理器
  • 进程的当前目录
  • 进程用户ID与进程组ID

多线程的锁/多线程同步方式

  • 互斥锁
  • 自旋锁
  • 信号量
  • 读写锁
  • 递归锁

死锁

  • 在两个或者多个并发进程中,如果每个进程持有某种资源而又等待其它进程释放它或它们现在保持着的资源,在未改变这种状态之前都不能向前推进,称这一组进程产生了死锁。通俗的讲就是两个或多个进程无限期的阻塞、相互等待的一种状态。
  • 产生的四个条件(缺一不可):
    • 互斥条件:一个资源一次只能被一个进程使用
    • 请求与保持条件:一个进程因请求资源而阻塞时,对已获得资源保持不放
    • 不剥夺条件:进程获得的资源,在未完全使用完之前,不能强行剥夺
    • 循环等待条件:若干进程之间形成一种头尾相接的环形等待资源关系

缓冲区溢出危害

  • 缓冲区溢出是指当计算机向缓冲区填充数据时超出了缓冲区本身的容量,溢出的数据覆盖在合法数据上。
    • 程序崩溃,导致拒绝额服务
    • 跳转并且执行一段恶意代码
  • 造成缓冲区溢出的主要原因是程序中没有仔细检查用户输入

分页/分段

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

虚拟内存空间

  • 虚拟地址空间:是指应用程序自己认为,自己所处的地址空间。它区别于物理地址空间。后者是真实存在的,比如电脑有一根8G的内存条,物理地址空间就是0~8Gb。CPU的MMU(内存管理单元)负责把虚拟地址转换成物理地址。
  • 好处
    • 程序员不再关心真实的物理内存空间是什么样的,理论上来说(64位CPU的虚拟内存为2^64),程序员有几乎无限大的虚拟内存空间可用,最后只要建立虚拟地址和物理地址的对应关系即可。
    • 操作系统屏蔽了物理内存空间的细节,进程无法访问到操作系统禁止访问的物理地址,也不能访问到别的进程的地址空间,这大大增强了程序安全性
    • 由虚拟地址空间引申出来的分页(Paging)技术,大大提高了内存的使用效率。要想运行一个程序,不再需要把整个程序都放入内存中执行,我们只要保证将要执行的页在内存中即可,如果不存在则导致页错误。

操作系统内核态/用户态

  • 两个权限等级
    内核态: CPU可以访问内存所有数据, 包括外围设备, 例如硬盘, 网卡. CPU也可以将自己从一个程序切换到另一个程序
    用户态: 只能受限的访问内存, 且不允许访问外围设备. 占用CPU的能力被剥夺, CPU资源可以被其他程序获取

“堆” or “栈”

  • 栈: 由系统自动分配的内存区域, 由系统自动释放。例如,在函数中声明一个局部变量 int b; 系统自动在栈中为b开辟空间
  • 堆: 需要程序员自己申请的内存区域,并指明大小,并且需要主动进行释放。 例如: 在c中malloc函数,如p1 = (char*)malloc(10);在C++中用new运算符如p2 = new char[10];

你可能感兴趣的:(Mess)