跳转至

carrier OS

请你说说虚拟内存和物理内存的区别

  1. 物理内存 以前,还没有虚拟内存概念的时候,程序寻址用的都是物理地址。程序能寻址的范围是有限的,这取决于 CPU 的地址线条数。比如在 32 位平台下,寻址的范围是 2^32 也就是 4G。并且这是固定的,如果没有虚拟内存,且每次开启一个进程都给 4G 物理内存,就可能会出现很多问题:
    1. 因为物理内存是有限的,当有多个进程要执行的时候,都要给 4G 内存,很显然内存不够,这很快就分配完了,于是没有得到分配资源的进程就只能等待。当一个进程执行完了以后,再将等待的进程装入内存。这种频繁的装入内存的操作效率很低
    2. 由于指令都是直接访问物理内存的,那么任何进程都可以修改其他进程的数据,甚至会修改内核地址空间的数据,这是不安全的
  2. 虚拟内存 由于物理内存有很多问题,所以出现了虚拟内存。虚拟内存是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。
  3. 物理内存是计算机中实际存在的内存,由内存条、缓存等物理设备构成,它可以被CPU直接寻址和访问。物理内存的容量通常是比较有限的,一般只有几十GB或几百GB。
  4. 虚拟内存是指操作系统为每个进程提供的一种抽象的内存管理方式,它将进程需要访问的内存映射到物理内存中的一部分。虚拟内存使得每个进程能够拥有更大的地址空间,可以访问的内存容量远远超出物理内存的容量。虚拟内存通过将部分未被使用的内存映射到磁盘上的一个称为交换文件的特殊文件中,从而使得物理内存得到释放,可以被分配给其他进程使用。
  5. 当进程需要访问虚拟内存中的某个地址时,操作系统会根据地址映射表将虚拟地址转换为物理地址。如果物理内存中没有足够的空间来存储需要访问的数据,那么操作系统会将一部分不常用的物理内存中的数据交换到磁盘上的交换文件中,从而腾出物理内存的空间,以供当前进程使用。
  6. 总的来说,虚拟内存和物理内存是计算机系统中两个不同的概念,虚拟内存可以扩展物理内存的容量,从而使得进程能够使用更大的内存空间。

虚拟内存是操作系统为每个进程提供的一种抽象的内存管理方式,它将进程需要访问的内存映射到物理内存中的一部分。虚拟内存的好处主要包括以下几点:

  1. 扩展内存容量:虚拟内存可以扩展计算机的内存容量,使得每个进程能够拥有更大的地址空间,可以访问的内存容量远远超出物理内存的容量。这样可以支持更大的程序和数据集,从而提高计算机的计算能力和数据处理能力。
  2. 隔离不同进程:虚拟内存使得不同的进程可以拥有独立的地址空间,彼此之间相互隔离,从而防止进程之间的内存相互干扰和破坏。这提高了计算机的安全性和稳定性,避免了进程之间的竞争和冲突。
  3. 管理内存:虚拟内存可以帮助操作系统有效地管理内存,实现内存分配和释放。操作系统可以将不常用的数据从物理内存中换出到磁盘上的交换文件中,从而释放物理内存,为当前进程腾出更多的内存空间。这样可以提高计算机的内存利用率,减少内存浪费。
  4. 方便共享内存:虚拟内存可以方便地实现内存的共享。不同的进程可以共享相同的物理内存页,从而避免了数据的复制和传输,减少了内存的消耗和网络带宽的使用。

总的来说,虚拟内存可以扩展计算机的内存容量,实现进程之间的隔离和内存管理,提高计算机的安全性、稳定性和性能。

进程与线程的区别

得分点 地址空间、开销、并发性、内存 标准回答 进程和线程的主要差别在于它们是不同的操作系统资源管理方式。

  1. 进程有独立的地址空间,线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间;
  2. 进程和线程切换时,需要切换进程和线程的上下文,进程的上下文切换时间开销远远大于线程上下文切换时间,耗费资源较大,效率要差一些;
  3. 进程的并发性较低,线程的并发性较高;
  4. 每个独立的进程有一个程序运行的入口、顺序执行序列和程序的出口,但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制;
  5. 系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了 CPU 外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源;
  6. 一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。
  7. 进程和线程都是计算机中实现多任务的方式。 进程是操作系统中资源分配的基本单位,每个进程都有自己的地址空间、代码、数据和系统资源(如打开的文件、打印机等)。在操作系统中,每个进程都是独立的实体,彼此之间相互隔离,因此每个进程都可以有自己的独立执行流程。进程间通常通过进程间通信(IPC)机制来进行数据交换和通信。
  8. 线程是进程中的执行单位,是操作系统中最小的可调度单位。在一个进程中,可以有多个线程共享进程的地址空间和资源。由于多个线程共享相同的资源,因此线程间通信比进程间通信更为高效。线程也可以提高系统的并发性和响应速度。
  9. 总的来说,进程和线程都是用来实现多任务的方式。进程是操作系统中资源分配的基本单位,每个进程都拥有自己的地址空间和系统资源,彼此之间相互独立;线程是进程中的执行单位,是操作系统中最小的可调度单位,多个线程可以共享相同的资源。

请你说说死锁定义及发生的条件

得分点 争夺共享资源、相互等待、互斥条件、请求和保持条件、不剥夺条件、环路等待条件

  1. 死锁 两个或两个以上的进程在执行过程中,因争夺共享资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁。这些永远在互相等待的进程称为死锁进程。
  2. 产生死锁的必要条件 虽然进程在运行过程中,可能发生死锁,但死锁的发生也必须具备一定的条件,死锁的发生必须具备以下四个必要条件:
    1. 互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放;
    2. 请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放;
    3. 不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放;
    4. 环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合 {P0,P1,P2,···,Pn} 中的 P0 正在等待一个 P1 占用的资源;P1 正在等待 P2 占用的资源,……,Pn 正在等待已被 P0 占用的资源。

进程间的通信

得分点 管道、命名管道、信号、消息队列、共享内存、内存映射、信号量、Socket

进程间通信主要包括:管道、命名管道、信号、消息队列、共享内存、内存映射、信号量、Socket:

  1. 管道 管道也叫无名(匿名)管道,它是是 UNIX 系统 IPC(进程间通信)的最古老形式,所有的 UNIX 系统都支持这种通信机制。管道本质其实是内核中维护的一块内存缓冲区,Linux 系统中通过 pipe() 函数创建管道,会生成两个文件描述符,分别对应管道的读端和写端。无名管道只能用于具有亲缘关系的进程间的通信。
  2. 命名管道 匿名管道,由于没有名字,只能用于亲缘关系的进程间通信。为了克服这个缺点,提出了有名管道(FIFO),也叫命名管道、FIFO文件。有名管道(FIFO)不同于匿名管道之处在于它提供了一个路径名与之关联,以 FIFO 的文件形式存在于文件系统中,并且其打开方式与打开一个普通文件是一样的,这样即使与 FIFO 的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过 FIFO 相互通信,因此,通过 FIFO 不相关的进程也能交换数据。
  3. 信号 信号是 Linux 进程间通信的最古老的方式之一,是事件发生时对进程的通知机制,有时也称之为软件中断,它是在软件层次上对中断机制的一种模拟,是一种异步通信的方式。信号可以导致一个正在运行的进程被另一个正在运行的异步进程中断,转而处理某一个突发事件。
  4. 消息队列 消息队列就是一个消息的链表,可以把消息看作一个记录,具有特定的格式以及特定的优先级,对消息队列有写权限的进程可以向消息队列中按照一定的规则添加新消息,对消息队列有读权限的进程则可以从消息队列中读走消息,消息队列是随内核持续的。
  5. 共享内存 共享内存允许两个或者多个进程共享物理内存的同一块区域(通常被称为段)。由于一个共享内存段会称为一个进程用户空间的一部分,因此这种 IPC 机制无需内核介入。所有需要做的就是让一个进程将数据复制进共享内存中,并且这部分数据会对其他所有共享同一个段的进程可用。与管道等要求发送进程将数据从用户空间的缓冲区复制进内核内存和接收进程将数据从内核内存复制进用户空间的缓冲区的做法相比,这种 IPC 技术的速度更快。
  6. 内存映射 内存映射(Memory-mapped I/O)是将磁盘文件的数据映射到内存,用户通过修改内存就能修改磁盘文件。
  7. 信号量 信号量主要用来解决进程和线程间并发执行时的同步问题,进程同步是并发进程为了完成共同任务采用某个条件来协调它们的活动。对信号量的操作分为 P 操作和 V 操作,P 操作是将信号量的值减 1,V 操作是将信号量的值加 1。当信号量的值小于等于 0 之后,再进行 P 操作时,当前进程或线程会被阻塞,直到另一个进程或线程执行了 V 操作将信号量的值增加到大于 0 之时。
  8. Socket 套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。Socket 一般用于网络中不同主机上的进程之间的通信。

线程通信

得分点 Monitor、Condition

在Java中,常用的线程通信方式有两种,分别是利用Monitor实现线程通信、利用Condition实现线程通信。

  • 线程同步是线程通信的前提,所以究竟采用哪种方式实现通信,取决于线程同步的方式。
  • 如果是采用synchronized关键字进行同步,则需要依赖Monitor(同步监视器)实现线程通信,Monitor就是锁对象。在synchronized同步模式下,锁对象可以是任意的类型,所以通信方法自然就被定义在Object类中了,这些方法包括:wt() 、notify()、notifyAll()。一个线程通过Monitor调用wt()时,它就会释放锁并在此等待。当其他线程通过Monitor调用notify() 时,则会唤醒在此等待的一个线程。当其他线程通过Monitor调用notifyAll()时,则会唤醒在此等待的所有线程。 JDK 1.5新增了Lock接口及其实现类,提供了更为灵活的同步方式。如果是采用Lock对象进行同步,则需要依赖Condition实现线程通信,Condition对象是由Lock对象创建出来的,它依赖于Lock对象。Condition对象中定义的通信方法,与Object类中的通信方法类似,它包括awt() 、signal()、signalAll()。通过名字就能看出它们的含义了,当通过Condition调用awt() 时当前线程释放锁并等待,当通过Condition调用signal()时唤醒一个等待的线程,当通过Condition调用signalAll()时则唤醒所有等待的线程。

加分回答

线程同步是基于同步队列实现的,而线程通信是基于等待队列实现的。当调用等待方法时,即将当前线程加入等待队列。当调用通知方法时,即将等待队列中的一个或多个线程转移回同步队列。因为synchronized只有一个Monitor,所以它就只有一个等待队列。而Lock对象可以创建出多个Condition,所以它拥有多个等待队列。多个等待队列带来了极大的灵活性,所以基于Condition的通信方式更为推荐。 比如,在实现生产消费模型时,生产者要通知消费者、消费者要通知生产者。相反,不应该出现生产者通知生产者、消费者通知消费者这样的情况。如果使用synchronized实现这个模型,由于它只有一个等待队列,所以只能把生产者和消费者加入同一个队列,这就会导致生产者通知生产者、消费者通知消费者的情况出现。采用Lock实现这个模型时,由于它有多个等待队列,可以有效地将这两个角色区分开,就能避免出现这样的问题。

请你说说多线程

解题思路

得分点 线程和进程的关系、为什么使用多线程 标准回答 线程是操作系统调度的最小单元,它可以让一个进程并发地处理多个任务,也叫轻量级进程。所以,在一个进程里可以创建多个线程,这些线程都拥有各自的计数器、堆栈、局部变量,并且能够共享进程内的资源。由于共享资源,处理器便可以在这些线程之间快速切换,从而让使用者感觉这些线程在同时执行。 总的来说,操作系统可以同时执行多个任务,每个任务就是一个进程。进程可以同时执行多个任务,每个任务就是一个线程。一个程序运行之后至少有一个进程,而一个进程可以包含多个线程,但至少要包含一个线程。 使用多线程会给开发人员带来显著的好处,而使用多线程的原因主要有以下几点:

\1. 更多的CPU核心 现代计算机处理器性能的提升方式,已经从追求更高的主频向追求更多的核心发展,所以处理器的核心数量会越来越多,充分地利用处理器的核心则会显著地提高程序的性能。而程序使用多线程技术,就可以将计算逻辑分配到多个处理器核心上,显著减少程序的处理时间,从而随着更多处理器核心的加入而变得更有效率。

\2. 更快的响应时间 我们经常要针对复杂的业务编写出复杂的代码,如果使用多线程技术,就可以将数据一致性不强的操作派发给其他线程处理(也可以是消息队列),如上传图片、发送邮件、生成订单等。这样响应用户请求的线程就能够尽快地完成处理,大大地缩短了响应时间,从而提升了用户体验。 3. 更好的编程模型 Java为多线程编程提供了良好且一致的编程模型,使开发人员能够更加专注于问题的解决,开发者只需为此问题建立合适的业务模型,而无需绞尽脑汁地考虑如何实现多线程。一旦开发人员建立好了业务模型,稍作修改就可以将其方便地映射到Java提供的多线程编程模型上。

内核态与用户态

内核态其实从本质上说就是内核,它是一种特殊的软件程序,控制计算机的硬件资源,例如协调CPU资源,分配内存资源,并且提供稳定的环境供应用程序运行。

用户态就是提供应用程序运行的空间,为了使应用程序访问到内核管理的资源例如CPU,内存,I/O。内核必须提供一组通用的访问接口,这些接口就叫系统调用。

系统调用是操作系统的最小功能单位。根据不同的应用场景,不同的Linux发行版本提供的系统调用数量也不尽相同,大致在240-350之间。这些系统调用组成了用户态跟内核态交互的基本接口。

从用户态到内核态切换可以通过三种方式:

系统调用:系统调用本身就是中断,但是是软件中断,跟硬中断不同。

异常:如果当前进程运行在用户态,如果这个时候发生了异常事件,就会触发切换。例如:缺页异常。

外设中断:当外设完成用户的请求时,会向CPU发送中断信号。 # 第一章 引论

banker

一句话+一张图说清楚——银行家算法-CSDN博客

银行家算法 - 维基百科,自由的百科全书