操作系统知识点和常考面试题

进程和线程-分别的概念和区别 

进程是资源分配的基本单位,线程是cpu调度,或者说是程序执行的最小单位。但是并不是说CPU不在以进程为单位进行调度,虽然在某些操作系统中是这样。同一个进程中并行运行多个线程,就是对在同一台计算机上运行多个进程的模拟。

进程有独立的地址空间,而同一进程中的线程共享该进程的地址空间。比如在linux下面启动一个新的进程,系统必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种非常昂贵的多任务工作方式。而运行一个进程中的线程,它们之间共享大部分数据,使用相同的地址空间,因此启动一个线程,切换一个线程远比进程操作要快,花费也要小得多。当然,线程是拥有自己的寄存器和堆栈(线程栈),比如在windows中用_beginthreadex创建一个新进程就会在调用CreateThread的同时申请一个专属于线程的数据块(_tiddata)。虽然,线程有自己线程栈,线程可以直接访问全局变量,甚至可以访问进程地址空间中的每一个内存,所以一个线程可以读写甚至清楚另一个线程的堆栈。

线程之间的通信比较方便。统一进程下的线程共享数据(比如全局变量,静态变量,打开的文件,子进程),通过这些数据来通信不仅快捷而且方便,当然如何处理好这些访问的同步与互斥正是编写多线程程序的难点。而进程之间的通信只能通过进程通信的方式进行。在一个线程中分配的堆在各个线程中均可以使用,在一个线程中打开的文件各个线程均可用,当然指同一进程中的线程。

多进程比多线程程序要健壮。一个线程死掉整个进程就死掉了,但是在保护模式下,一个进程死掉对另一个进程没有直接影响

线程的执行与进程是有区别的。每个独立的线程有有自己的一个程序入口,顺序执行序列和程序的出口,但是线程不能独立执行,必须依附与程序之中,由应用程序提供多个线程的并发控制。

linux中进程具有父子关系,形成进程树,但是线程是平等的没有父子关系
 

线程和进程的适用范围

需要频繁创建销毁的优先使用线程;因为对进程来说创建和销毁一个进程代价是很大的。

线程的切换速度快,所以在需要大量计算,切换频繁时用线程,还有耗时的操作使用线程可提高应用程序的响应。

多进程可以使用在多机分布式系统,需要扩展到其他机器上,使用多进程,多线程适用于多核处理机。

需要更稳定安全时,适合选择进程;需要速度时,选择线程更好。

线程是否创建的越多越好?

 不是,创建线程越多,对共享资源同步要求多,设计同步容易出错。另外多线程并发容易导致资源分配问题。而且创建线程本身也会消耗大量的资源,如果一有任务就创建线程,那么容易导致系统的负载过大。一般解决方案是线程池。

进程之间的通信方式?

进程间通信需要解决的问题有三个:数据传递,关键部位不会交叉,顺序

进程间通信适用于线程,但是有一个不同的地方,进程间交换数据是在不同的地址空间进行,但是线程是在同一个地址空间进行,只要知道数据的地址,都可以很方便的访问

七种进程间通信方式

信号量:信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。

管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。

命名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。

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

信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。

共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。

套接字( socket ) : 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。

线程的基本概念、线程的基本状态及状态之间的关系?

线程被称为轻量级进程,除了没有独立的地址空间管理资源,其余都与进程相同。进程与线程的区别前面已经阐述。

线程与进程相同,都具有三个基本状态:运行、阻塞、和就绪,状态之间有四种转换关系:运行–> 阻塞;阻塞–>就绪;就绪–>运行;运行–>就绪;只有运行与就绪可以相互转换。

而阻塞一定要经过就绪态,我的理解是,如果没有就绪态,那么操作系统在调度的时候就不知道哪些是已经阻塞完成哪些还在阻塞,那等待IO来说,如果没有就绪态,操作系统就不知道哪些IO上已经有了输入,哪些还需要继续等待。

多线程同步和互斥有几种实现方法,都是什么?

线程同步是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒。

线程互斥是指对于共享的进程系统资源,在各单个线程访问时的排它性。当有若干个线程都要使用某一共享资源时,任何时刻最多只允许一个线程去使用,其它要使用该资源的线程必须等待,直到占用资源者释放该资源。线程互斥可以看成是一种特殊的线程同步(下文统称为同步)。

线程间的同步方法大体可分为两类:用户模式和内核模式。顾名思义,内核模式就是指利用系统内核对象的单一性来进行同步,使用时需要切换内核态与用户态,而用户模式就是不需要切换到内核态,只在用户态完成操作。
用户模式下的方法有:原子操作(例如一个单一的全局变量),临界区。内核模式下的方法有:事件,信号量,互斥量。

Windows
1、临界区:指的是一个访问共用资源(例如:共用设备或是共用存储器)的程序片段,而这些共用资源又无法同时被多个线程访问的特性。 
2、互斥量:为协调共同对一个共享资源的单独访问而设计的, 互斥量是信号量的一种特例,他只有0和1两种状态(解锁和加锁)。
3、信号量:为控制一个具有有限数量用户资源而设计。 对应一个down和up操作,down使信号量减1,up使信号量加1,如果信号量大于0,则down后继续执行,如果down等于0,则down后睡眠,但是并不会将信号量减到负数。down和up都是原子操作
4、事 件:用来通知线程有一些事件已发生,从而启动后继任务的开始。 

Linux

互斥锁,自旋锁,读写锁,屏障

死锁是怎么产生的

  1. 互斥条件。一个资源不能同时被多个进程访问
  2. 占有和等待条件。一个资源已经被另一个进程占用,那么该进程只能等待。
  3. 不可抢占。已经分配给某个进程的资源,不能通过调度的方式抢占该资源。
  4. 环路等待条件。多个进程和资源组成环路。

CPU的执行方式

代码中遇到进程阻塞,进程僵死,内存泄漏等情况怎么排查。

有没有了解过协程?说下协程和线程的区别?

虚拟内存的作用?

  1. 将主存视为一个存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,并根据需要在磁盘和主存之间来回传送数据
  2. 为每个进程提供了一致的地址空间,简化内存管理
  3. 保护了每个进程的地址空间不被其他进程破坏

操作系统为了管理内存,给每个进程都分配独立的地址空间,对32位的系统而言,这个空间的大小是4GB。这4GB并不是实际的物理内存,实际上并不存在,因此有虚拟内存这一名称。

虚拟内存的实现?

虚拟地址空间的地址称为逻辑地址,实际物理内存(就是内存条的大小)的地址空间称为物理地址。虚拟地址空间被分割成多个大小相同的页面(比如4k为一个页面),物理地址空间被分割成同样大小的页框。虚拟地址的页面通过一个页表映射物理内存的页框,页表中保存着两者的对应关系。逻辑地址是CPU使用的地址,当进程要访问该进程地址空间里的某个地址时时候,将该地址的值传递给CPU,CPU访问该地址时,会经过MMU将逻辑地址转换为物理地址,之前说的页表就保存在MMU中,操作系统为每个进程都维护一个页表。


页表就是记录了虚拟页和物理页映射关系的一种数据结构。每次地址翻译硬件将一个虚拟地址转换为物理地址时,都需要读取页表。

操作系统层面对内存的管理?

内存池的作用?STL里内存池如何实现

进程空间和内核空间对内存的管理不同?

Linux的slab层,VAM?

伙伴算法

高端内存

进程调度

  1. Linux进程分为两种,实时进程和非实时进程;
  2. 优先级分为静态优先级和动态优先级,优先级的范围;
  3. 调度策略,FIFO,LRU,时间片轮转
  4. 交互进程通过平均睡眠时间而被奖励;

堆是线程共有还是私有,堆是进程共有还是私有,栈呢

在多线程环境下,每个线程拥有一个栈和一个程序计数器。栈和程序计数器用来保存线程的执行历史和线程的执行状态,是线程私有的资源。
其他的资源(比如堆、地址空间、全局变量)是由同一个进程内的多个线程共享。

共享内存的使用实现原理(必考必问,然后共享内存段被映射进进程空间之后,存在于进程空间的什么位置?共享内存段最大限制是多少?)

c++进程内存空间分布(注意各部分的内存地址谁高谁低,注意栈从高道低分配,堆从低到高分配)

堆  堆是动态内存分配通常发生的部分。内存分配由低到高,分配方式类似于数据结构的链表。堆区域从BSS段的末尾开始,并从那里逐渐增加到更大的地址。堆是由程序员自己分配的。堆区域由所有共享库和进程中动态加载的模块共享。(malloc和new从堆区分配内存)

栈  存放自动变量,以及每次调用函数时保存的信息。每当调用一个函数时,返回到的地址和关于调用者环境的某些信息的地址,比如一些机器寄存器,就会被保存在栈中。然后,新调用的函数在栈上分配空间,用于自动和临时变量。(直接定义数组是从栈中分配

ELF是什么?其大小与程序中全局变量的是否初始化有什么关系(注意.bss段)

使用过哪些进程间通讯机制,并详细说明(重点)

多线程和多进程的区别(重点 面试官最最关心的一个问题,必须从cpu调度,上下文切换,数据共享,多核cup利用率,资源占用,等等各方面回答,然后有一个问题必须会被问到:哪些东西是一个线程私有的?答案中必须包含寄存器,否则悲催)

信号:列出常见的信号,信号怎么处理?

SIGINT,SIGKILL(不能被捕获),SIGTERM(可以被捕获),SIGSEGV,SIGCHLD,SIGALRM

i++是否原子操作?并解释为什么?

不是原子操作。理由:

1.i++分为三个阶段:

内存到寄存器
寄存器自增
写回内存
这三个阶段中间都可以被中断分离开.

i++的操作分三步:

(1)栈中取出i

(2)i自增1

(3)将i存到栈

所以i++不是原子操作,上面的三个步骤中任何一个步骤同时操作,都可能导致i的值不正确自增

在多核的机器上,cpu在读取内存i时也会可能发生同时读取到同一值,这就导致两次自增,实际只增加了一次。

综上,我认为i++和++i都不是原子操作。

说出你所知道的各类linux系统的各类同步机制(重点),什么是死锁?如何避免死锁(每个技术面试官必问)

列举说明linux系统的各类异步机制

exit() _exit()的区别?

如何实现守护进程?

linux的内存管理机制是什么?

linux的任务调度机制是什么?

标准库函数和系统调用的区别?

系统如何将一个信号通知到进程?

 

猜你喜欢

转载自blog.csdn.net/weixin_39203720/article/details/114350909