- 进程和线程的区别?
- 调度:进程是资源管理的基本单位,线程是程序执行的基本单位。
- 切换:线程上下文切换比进程上下文切换要快得多。
- 拥有资源: 进程是拥有资源的一个独立单位,线程不拥有系统资源,但是可以访问隶属于进程的资源。
- 系统开销: 创建或撤销进程时,系统都要为之分配或回收系统资源,如内存空间,I/O设备等,OS所付出的开销显著大于在创建或撤销线程时的开销,进程切换的开销也远大于线程切换的开销。
- 协程与线程的区别?管程的概念?
- 线程和进程都是同步机制,而协程是异步机制。
- 线程是抢占式,而协程是非抢占式的。需要用户释放使用权切换到其他协程,因此同一时间其实只有一个协程拥有运行权,相当于单线程的能力。
- 一个线程可以有多个协程,一个进程也可以有多个协程。
- 协程不被操作系统内核管理,而完全是由程序控制。线程是被分割的CPU资源,协程是组织好的代码流程,线程是协程的资源。但协程不会直接使用线程,协程直接利用的是执行器关联任意线程或线程池。
- 协程能保留上一次调用时的状态。
管程是一种同步原语,用于解决多个线程对共享资源的访问冲突问题。它包含一个数据结构和一个或多个对该数据结构进行操作的过程。管程中的过程互斥地执行,即在一个时间点只有一个过程可以执行。这保证了对共享资源的互斥访问,避免了数据不一致的问题。
- 并发和并行有什么区别?
- 定义:并发(Concurrency)是指多个任务在同一时间段内同时执行,但不一定是同时开始或结束的;并行(Parallelism)是指多个任务在同一时刻同时执行。
- 执行方式:并发是交替执行多个任务,通常是由一个或多个线程在多个处理器核心上实现;而并行是同时执行多个任务,每个任务都在独立的处理器核心上执行。
- 效率:并行的效率通常高于并发,因为并行可以同时利用多个处理器核心的计算能力,而并发可能受到线程调度和上下文切换的开销影响。
- 适用场景:并发适用于多核或多处理器系统,可以提高系统的吞吐量和响应速度;而并行适用于计算密集型任务,可以充分利用硬件资源提高计算性能。
- 进程与线程的切换流程?
进程切换:
- 保存当前进程的上下文信息,包括程序计数器、寄存器状态、内存管理信息等。
- 从进程调度队列中选择一个新的进程。
- 恢复新进程的上下文信息。
- 将新进程的程序计数器值加载到CPU的程序计数器中,开始执行新进程。
线程切换:
- 保存当前线程的上下文信息,包括程序计数器、寄存器状态等。
- 从线程调度队列中选择一个新的线程。
- 恢复新线程的上下文信息。
- 将新线程的程序计数器值加载到CPU的程序计数器中,开始执行新线程。
注意:由于线程共享进程的地址空间,因此不需要切换内存管理信息等进程特有的上下文。
- 为什么虚拟地址空间切换会比较耗时?
进程都有自己的虚拟地址空间,把虚拟地址转换为物理地址需要查找页表,页表查找是一个很慢的过程,因此通常使用Cache来缓存常用的地址映射,这样可以加速页表查找,这个Cache就是TLB(translation Lookaside Buffer,TLB本质上就是一个Cache,是用来加速页表查找的)。
由于每个进程都有自己的虚拟地址空间,那么显然每个进程都有自己的页表,那么当进程切换后页表也要进行切换,页表切换后TLB就失效了,Cache失效导致命中率降低,那么虚拟地址转换为物理地址就会变慢,表现出来的就是程序运行会变慢,而线程切换则不会导致TLB失效,因为线程无需切换地址空间,因此我们通常说线程切换要比较进程切换块,原因就在这里。
- 进程间通信方式有哪些?
-
管道:管道这种通讯方式有两种限制,一是半双工的通信,数据只能单向流动,二是只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
管道可以分为两类:匿名管道和命名管道。匿名管道是单向的,只能在有亲缘关系的进程间通信;命名管道以磁盘文件的方式存在,可以实现本机任意两个进程通信。
-
信号 : 信号是一种比较复杂的通信方式,信号可以在任何时候发给某一进程,而无需知道该进程的状态。
Linux系统中常用信号:
(1)SIGHUP:用户从终端注销,所有已启动进程都将收到该进程。系统缺省状态下对该信号的处理是终止进程。
(2)SIGINT:程序终止信号。程序运行过程中,按Ctrl+C
键将产生该信号。
(3)SIGQUIT:程序退出信号。程序运行过程中,按Ctrl+\\
键将产生该信号。
(4)SIGBUS和SIGSEGV:进程访问非法地址。
(5)SIGFPE:运算中出现致命错误,如除零操作、数据溢出等。
(6)SIGKILL:用户终止进程执行信号。shell下执行kill -9
发送该信号。
(7)SIGTERM:结束进程信号。shell下执行kill 进程pid
发送该信号。
(8)SIGALRM:定时器信号。
(9)SIGCLD:子进程退出信号。如果其父进程没有忽略该信号也没有处理该信号,则子进程退出后将形成僵尸进程。
- 信号量:信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
- 消息队列:消息队列是消息的链接表,包括Posix消息队列和System V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
- 共享内存:共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。
- Socket:与其他通信机制不同的是,它可用于不同机器间的进程通信。
优缺点:
- 管道:速度慢,容量有限;
- Socket:任何进程间都能通讯,但速度慢;
- 消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题;
- 信号量:不能传递复杂消息,只能用来同步;
- 共享内存区:能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题,相当于线程中的线程安全,当然,共享内存区同样可以用作线程间通讯,不过没这个必要,线程间本来就已经共享了同一进程内的一块内存。
- 进程间同步的方式有哪些?
进程间同步是指协调多个进程之间的执行顺序,以确保它们能够按照预期的方式访问共享资源或完成共同的任务。以下是几种常见的进程间同步方式:
- 互斥锁(Mutex): 也称为互斥量,用于确保同一时间只有一个进程能够访问共享资源。当一个进程需要访问共享资源时,会尝试获取互斥锁;如果锁已经被其他进程持有,则该进程会被阻塞,直到获得锁为止。
- 信号量(Semaphore): 是一种计数器,用于控制多个进程对共享资源的访问。信号量的值表示可用资源的数量;进程在访问资源前需要获取信号量(将其值减一),访问结束后释放信号量(将其值加一)。
- 条件变量(Condition Variable): 与互斥锁结合使用,允许一个或多个进程在特定条件下等待,直到该条件成立为止。通常用于实现生产者-消费者问题、睡眠-唤醒机制等。
- 读写锁(Read-Write Lock): 用于保护共享资源,允许多个进程同时读取资源,但只允许一个进程写入资源。这样可以提高并发性能,因为读取操作通常不会修改数据,因此可以并发进行。
- 消息队列(Message Queue): 进程间通过发送和接收消息来进行同步和通信。消息队列提供了一种可靠的通信机制,允许进程之间传递数据并进行协调。
- 共享内存(Shared Memory): 多个进程可以访问同一块内存区域,通过读写内存中的数据来进行同步。需要配合互斥锁或信号量等机制来确保对共享内存的访问是安全和协调的。
- 线程同步的方式有哪些?
线程同步是指协调多个线程之间的执行顺序,以确保它们能够正确地共享数据和完成共同的任务。以下是几种常见的线程同步方式:
- 互斥锁(Mutex): 与进程间同步中的互斥锁类似,用于确保同一时间只有一个线程能够访问共享资源或执行特定代码段。
- 条件变量(Condition Variable): 与进程间同步中的条件变量类似,允许线程在特定条件下等待或唤醒其他线程。
- 读写锁(Read-Write Lock): 与进程间同步中的读写锁类似,允许多个线程同时读取共享资源,但只允许一个线程写入资源。
- 信号量(Semaphore): 与进程间同步中的信号量类似,用于控制多个线程对共享资源的访问。
- 原子操作(Atomic Operations): 保证操作不可分割性,即在多线程环境下,一个操作要么全部完成,要么全部不完成,不会被其他线程打断。
- 临界区(Critical Section): 一段只能被一个线程执行的代码区域。进入临界区的线程需要获取相应的锁,而其他尝试进入临界区的线程则会被阻塞,直到锁被释放。
- 自旋锁(Spinlock): 是一种特殊的互斥锁,当线程尝试获取锁失败时,它会一直循环检查锁是否可用。自旋锁适用于短时间内等待的情况,因为它不涉及线程切换的开销。
- 线程的分类?
从线程的运行空间来说,分为用户级线程(user-level thread, ULT)和内核级线程(kernel-level, KLT)
内核级线程:这类线程依赖于内核,又称为内核支持的线程或轻量级进程。无论是在用户程序中的线程还是系统进程中的线程,它们的创建、撤销和切换都由内核实现。
用户级线程:它仅存在于用户级中,这种线程是不依赖于操作系统核心的。应用进程利用线程库来完成其创建和管理,速度比较快,操作系统内核无法感知用户级线程的存在。
- 什么是临界区,如何解决冲突?
临界区指的是一个访问共用资源(例如:共用设备或是共用存储器)的程序片段,这些共用资源又无法同时被多个线程或进程访问的特性。简单来说,临界区是一段代码,其中只有一个线程或进程可以执行,而其他线程或进程必须等待。
解决临界区冲突的方法通常涉及同步机制,确保线程或进程在访问共享资源时不会发生冲突。以下是一些常见的解决冲突的方法:
- 禁用中断:在没有中断的情况下,没有上下文切换,因此没有并发。硬件将中断处理延迟到中断被启用之后。但是,这种方法有一个问题,即一旦中断被禁用,线程就无法被停止,可能导致其他线程处于饥饿状态。
- 使用互斥锁(Mutex):互斥锁是一种常用的同步机制,用于确保同一时间只有一个线程或进程可以访问临界区。当一个线程或进程进入临界区时,它会获取互斥锁,其他尝试进入临界区的线程或进程会被阻塞,直到锁被释放。
- 信号量(Semaphore):信号量是一种计数器,用于控制多个线程或进程对共享资源的访问。信号量的值表示可用资源的数量。线程或进程在访问资源前需要获取信号量(将其值减一),访问结束后释放信号量(将其值加一)。
- 条件变量(Condition Variable):与互斥锁结合使用,允许线程或进程在特定条件下等待,直到该条件成立为止。这通常用于实现生产者-消费者问题、睡眠-唤醒机制等。
- 读写锁(Read-Write Lock):允许多个线程或进程同时读取共享资源,但只允许一个线程或进程写入资源。这可以提高并发性能,因为读取操作通常不会修改数据。
- 什么是死锁?死锁产生的条件?如何处理死锁问题
什么是死锁:
在两个或者多个并发进程中,如果每个进程持有某种资源而又等待其它进程释放它或它们现在保持着的资源,在未改变这种状态之前都不能向前推进,称这一组进程产生了死锁。通俗的讲就是两个或多个进程无限期的阻塞、相互等待的一种状态。
死锁产生的四个必要条件:(有一个条件不成立,则不会产生死锁)
- 互斥条件:一个资源一次只能被一个进程使用
- 请求与保持条件:一个进程因请求资源而阻塞时,对已获得资源保持不放
- 不剥夺条件:进程获得的资源,在未完全使用完之前,不能强行剥夺
- 循环等待条件:若干进程之间形成一种头尾相接的环形等待资源关系
常用的处理死锁的方法有:死锁预防、死锁避免、死锁检测、死锁解除
- 进程调度策略有哪几种?
-
先来先服务:非抢占式的调度算法,按照请求的顺序进行调度。有利于长作业,但不利于短作业,因为短作业必须一直等待前面的长作业执行完毕才能执行,而长作业又需要执行很长时间,造成了短作业等待时间过长。另外,对
I/O
密集型进程也不利,因为这种进程每次进行I/O
操作之后又得重新排队。 -
短作业优先:非抢占式的调度算法,按估计运行时间最短的顺序进行调度。长作业有可能会饿死,处于一直等待短作业执行完毕的状态。因为如果一直有短作业到来,那么长作业永远得不到调度。
-
最短剩余时间优先:最短作业优先的抢占式版本,按剩余运行时间的顺序进行调度。 当一个新的作业到达时,其整个运行时间与当前进程的剩余时间作比较。如果新的进程需要的时间更少,则挂起当前进程,运行新的进程。否则新的进程等待。
-
时间片轮转:将所有就绪进程按
FCFS
的原则排成一个队列,每次调度时,把CPU
时间分配给队首进程,该进程可以执行一个时间片。当时间片用完时,由计时器发出时钟中断,调度程序便停止该进程的执行,并将它送往就绪队列的末尾,同时继续把CPU
时间分配给队首的进程。 -
优先级调度:为每个进程分配一个优先级,按优先级进行调度。为了防止低优先级的进程永远等不到调度,可以随着时间的推移增加等待进程的优先级。
- 进程有哪些状态?
- 什么是分页?什么是分段?分页和分段有什区别?
把内存空间划分为大小相等且固定的块,作为主存的基本单位。因为程序数据存储在不同的页面中,而页面又离散的分布在内存中,因此需要一个页表来记录映射关系,以实现从页号到物理块号的映射。
访问分页系统中内存数据需要两次的内存访问 (一次是从内存中访问页表,从中找到指定的物理块号,加上页内偏移得到实际物理地址;第二次就是根据第一次得到的物理地址访问内存取出数据)。
分页是为了提高内存利用率,而分段是为了满足程序员在编写代码的时候的一些逻辑需求(比如数据共享,数据保护,动态链接等)。
分段内存管理当中,地址是二维的,一维是段号,二维是段内地址;其中每个段的长度是不一样的,而且每个段内部都是从0开始编址的。由于分段管理中,每个段内部是连续内存分配,但是段和段之间是离散分配的,因此也存在一个逻辑地址到物理地址的映射关系,相应的就是段表机制。
- 分页对程序员是透明的,但是分段需要程序员显式划分每个段。
- 分页的地址空间是一维地址空间,分段是二维的。
- 页的大小不可变,段的大小可以动态改变。
- 分页主要用于实现虚拟内存,从而获得更大的地址空间;分段主要是为了使程序和数据可以被划分为逻辑上独立的地址空间并且有助于共享和保护。
- 什么是交换空间?
操作系统把物理内存(physical RAM)分成一块一块的小内存,每一块内存被称为页(page)。当内存资源不足时,Linux把某些页的内容转移至硬盘上的一块空间上,以释放内存空间。硬盘上的那块空间叫做交换空间(swap space),而这一过程被称为交换(swapping)。物理内存和交换空间的总容量就是虚拟内存的可用容量。
用途:
- 物理内存不足时一些不常用的页可以被交换出去,腾给系统。
- 程序启动时很多内存页被用来初始化,之后便不再需要,可以交换出去。
- 物理地址、逻辑地址、有效地址、线性地址、虚拟地址的区别?
- 物理地址(Physical Address):这是内存中的实际地址,CPU直接用来访问内存。物理地址由硬件电路(如内存管理单元MMU)进行管理和转换。
- 逻辑地址(Logical Address):也被称为虚拟地址(Virtual Address)或程序地址(Program Address)。这是程序看到的地址空间,通常由程序员在编写程序时使用。逻辑地址空间通常比物理地址空间大得多。
- 有效地址(Effective Address):在某些上下文中,有效地址可能是逻辑地址经过某些转换(如段偏移)后的结果。它通常指的是在内存访问之前,逻辑地址经过某种转换后的中间结果。
- 线性地址(Linear Address):在逻辑地址到物理地址的转换过程中,线性地址是逻辑地址经过某些转换(如分页)后得到的结果。在分页系统中,线性地址通常是页号和页内偏移的组合。
- 虚拟地址(Virtual Address):虚拟地址通常与逻辑地址相同,指的是程序看到的地址空间。在虚拟内存系统中,虚拟地址可能进一步被转换为物理地址。
- 页面替换算法有哪些?
- 最近最少使用(Least Recently Used, LRU):替换最长时间未被引用的页面。
- 先进先出(First In First Out, FIFO):替换最早进入内存的页面。
- 最不经常使用(Least Frequently Used, LFU):替换引用次数最少的页面。
- Clock算法:也称为最近未使用(Not Recently Used, NRU)算法,它结合了FIFO和LRU的特点。
- 二次机会(Second Chance):这是FIFO算法的一个变种,当页面被选中替换时,会检查它的引用位。如果引用位为0,则立即替换;如果为1,则将其重置为0并放回队列末尾。
- 选择合适的数据结构,模拟一个页面替换算法的流程,给出C代码
以FIFO页面替换算法为例,我们可以使用队列(Queue)数据结构来模拟其流程。以下是一个简单的C代码示例:
#include <stdio.h>
#include <stdlib.h>
#define MAX_PAGES 5 // 假设内存中有5个页面
typedef struct {
int page_number;
int reference_count;
} Page;
typedef struct {
Page pages[MAX_PAGES];
int front;
int rear;
} PageQueue;
void initializeQueue(PageQueue *queue) {
queue->front = 0;
queue->rear = 0;
for (int i = 0; i < MAX_PAGES; i++) {
queue->pages[i].page_number = -1;
queue->pages[i].reference_count = 0;
}
}
int isFull(PageQueue *queue) {
return (queue->rear + 1) % MAX_PAGES == queue->front;
}
int isEmpty(PageQueue *queue) {
return queue->front == queue->rear;
}
void enqueue(PageQueue *queue, int page_number) {
if (isFull(queue)) {
printf("Queue is full. Page replacement needed.\n");
// 这里可以添加页面替换逻辑
// 例如,移除队首页面(FIFO)
queue->front = (queue->front + 1) % MAX_PAGES;
}
queue->pages[queue->rear].page_number = page_number;
queue->pages[queue->rear].reference_count = 1; // 初始引用计数为1
queue->rear = (queue->rear + 1) % MAX_PAGES;
}
void referencePage(PageQueue *queue, int page_number) {
for (int i = 0; i < MAX_PAGES; i++) {
if (queue->pages[i].page_number == page_number) {
queue->pages[i].reference_count++;
printf("Page %d referenced. Reference count: %d\n", page_number, queue->pages[i].reference_count);
return;
}
}
printf("Page %d not found in memory. Need to bring it in.\n", page_number);
// 这里可以添加页面加载逻辑,例如从磁盘加载页面到内存
// 然后将新页面加入队列(如果队列已满,可能需要执行页面替换算法)
enqueue(queue, page_number);
}
int main() {
PageQueue queue;
initializeQueue(&queue);
// 模拟页面引用序列
int page_references[] = {7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2};
int num_references = sizeof(page_references) / sizeof(page_references[0]);
for (int i = 0; i < num_references; i++) {
referencePage(&queue, page_references[i]);
}
return 0;
}
- 页表、快表、Cache之间的命中存在什么关系?
页表(Page Table):页表是操作系统用于将虚拟地址转换为物理地址的数据结构。当CPU需要访问一个虚拟地址时,它会查询页表来获取相应的物理地址。页表通常驻留在内存中。
快表(Translation Lookaside Buffer, TLB):为了加速地址转换过程,硬件通常包含一个小的、快速的缓存,称为快表。当CPU需要执行虚拟到物理地址的转换时,它首先检查快表。如果转换结果(即物理地址)在快表中(TLB命中),则转换过程非常快。如果不在(TLB未命中),则CPU必须访问内存中的页表来获取物理地址,并可能将结果存入快表以备将来使用。
Cache(CPU Cache或内存Cache):Cache用于存储最近访问过的数据或指令,以减少对慢速内存的访问。当CPU需要访问数据时,它首先检查Cache。如果数据在Cache中(Cache命中),则访问速度非常快。如果不在(Cache未命中),则CPU必须从内存中获取数据,并可能将其存入Cache以备将来使用。
关系:
- TLB和Cache都是为了提高性能:它们都是为了提高CPU访问内存数据的速度。TLB减少地址转换的开销,而Cache减少数据访问的开销。
- TLB和页表的关系:TLB是页表的缓存。当TLB未命中时,需要访问页表;而当页表更新时,TLB也需要更新。
- Cache和内存的关系:Cache是内存的缓存。当Cache未命中时,需要访问内存;而当内存数据更新时,Cache也需要相应地更新。
命中关系:
- 什么是缓冲区溢出?有什么危害?
缓冲区溢出是指当计算机向缓冲区填充数据时超出了缓冲区本身的容量,溢出的数据覆盖在合法数据上。
危害有以下两点:
- 程序崩溃,导致拒绝额服务
- 跳转并且执行一段恶意代码
造成缓冲区溢出的主要原因是程序中没有仔细检查用户输入。
- 什么是虚拟内存?
虚拟内存就是说,让物理内存扩充成更大的逻辑内存,从而让程序获得更多的可用内存。虚拟内存使用部分加载的技术,让一个进程或者资源的某些页面加载进内存,从而能够加载更多的进程,甚至能加载比内存大的进程,这样看起来好像内存变大了,这部分内存其实包含了磁盘或者硬盘,并且就叫做虚拟内存。
- 虚拟内存的实现方式有哪些?
虚拟内存中,允许将一个作业分多次调入内存。釆用连续分配方式时,会使相当一部分内存空间都处于暂时或永久的空闲状态,造成内存资源的严重浪费,而且也无法从逻辑上扩大内存容量。因此,虚拟内存的实需要建立在离散分配的内存管理方式的基础上。虚拟内存的实现有以下三种方式:
- 请求分页存储管理。
- 请求分段存储管理。
- 请求段页式存储管理。
- 讲一讲IO多路复用?
IO多路复用(IO Multiplexing)是一种同步IO模型,它允许单个进程/线程同时处理多个IO请求。在IO多路复用中,一个进程/线程可以监视多个文件句柄(通常是网络连接),一旦某个文件句柄就绪(即可读、可写),就能够通知应用程序进行相应的读写操作。如果没有文件句柄就绪,那么进程/线程会阻塞,交出CPU控制权。
多路指的是多个网络连接,复用指的是同一个进程/线程。虽然一个进程/线程在任一时刻只能处理一个请求,但是由于处理每个请求的事件耗时非常短(通常控制在1毫秒以内),因此可以在1秒内处理上千个请求。从时间上来看,多个请求复用了一个进程/线程,这就是多路复用的思想。
IO多路复用主要用于网络编程中,用来提高服务器的吞吐能力。在服务器中,通常需要同时处理多个客户端的连接请求,而每个连接请求都需要读写操作。如果为每个连接请求都创建一个进程或线程,那么服务器的开销会非常大,因为进程/线程的创建和销毁都需要消耗资源。而使用IO多路复用,服务器可以只用一个进程/线程来同时处理多个连接请求,从而大大降低了资源消耗。
IO多路复用主要有三种技术:select、poll和epoll。其中,select是最早出现的技术,但是它在处理大量连接时性能较差;poll是对select的改进,它可以处理更多的连接,但是在高并发场景下仍然存在问题;epoll是Linux特有的技术,它可以更高效地处理大量连接,因此在高性能的服务器中广泛使用。
- 硬链接和软链接有什么区别?
- 硬链接就是在目录下创建一个条目,记录着文件名与
inode
编号,这个inode
就是源文件的inode
。删除任意一个条目,文件还是存在,只要引用数量不为0
。但是硬链接有限制,它不能跨越文件系统,也不能对目录进行链接。 - 符号链接文件保存着源文件所在的绝对路径,在读取时会定位到源文件上,可以理解为
Windows
的快捷方式。当源文件被删除了,链接文件就打不开了。因为记录的是路径,所以可以为目录建立符号链接。
- 中断的处理过程?
- 保护现场:将当前执行程序的相关数据保存在寄存器中,然后入栈。
- 开中断:以便执行中断时能响应较高级别的中断请求。
- 中断处理
- 关中断:保证恢复现场时不被新中断打扰
- 恢复现场:从堆栈中按序取出程序数据,恢复中断前的执行状态。
- 中断和轮询有什么区别?
- 轮询:CPU对特定设备轮流询问。中断:通过特定事件提醒CPU。
- 轮询:效率低等待时间长,CPU利用率不高。中断:容易遗漏问题,CPU利用率不高。
- 什么是用户态和内核态?
用户态和系统态是操作系统的两种运行状态:
- 内核态:内核态运行的程序可以访问计算机的任何数据和资源,不受限制,包括外围设备,比如网卡、硬盘等。处于内核态的 CPU 可以从一个程序切换到另外一个程序,并且占用 CPU 不会发生抢占情况。
- 用户态:用户态运行的程序只能受限地访问内存,只能直接读取用户程序的数据,并且不允许访问外围设备,用户态下的 CPU 不允许独占,也就是说 CPU 能够被其他程序获取。
将操作系统的运行状态分为用户态和内核态,主要是为了对访问能力进行限制,防止随意进行一些比较危险的操作导致系统的崩溃,比如设置时钟、内存清理,这些都需要在内核态下完成 。
- 用户态和内核态是如何切换的?
所有的用户进程都是运行在用户态的,但是我们上面也说了,用户程序的访问能力有限,一些比较重要的比如从硬盘读取数据,从键盘获取数据的操作则是内核态才能做的事情,而这些数据却又对用户程序来说非常重要。所以就涉及到两种模式下的转换,即用户态 -> 内核态 -> 用户态,而唯一能够做这些操作的只有 系统调用
,而能够执行系统调用的就只有 操作系统
。
- Unix的文件系统有怎样的特点?
Unix的文件系统是一个层次结构,也被称为树形结构。它以根目录(/)为起点,其他所有文件和目录都从根目录开始。这种结构为文件和目录提供了一个统一的命名和访问方式。
Unix文件系统的主要特点包括:
- 文件和目录的抽象:在Unix中,文件和目录都被视为特殊类型的文件,这使得文件系统操作更加统一。
- inode:每个文件或目录都有一个与之关联的inode(索引节点)。inode包含了文件或目录的元数据,如权限、大小、时间戳等,但不包含实际的文件数据。文件数据存储在数据块(block)中,这些块通过inode的指针与inode关联。
- 硬链接:由于文件和目录都是通过inode来标识的,所以一个inode可以对应多个文件名。这就是所谓的硬链接。只有当所有的硬链接都被删除后,文件的数据块才会被释放。
- 目录结构:目录本质上是一个包含文件名和相应inode号的特殊文件。当访问一个目录时,实际上是在读取这个特殊文件的内容。
- 文件操作:Unix提供了丰富的文件操作API,如open(), read(), write(), close()等,这些API允许程序以统一的方式访问文件系统中的文件。
- 你对FAT32有了解吗?
FAT32是一种文件分配表(FAT)文件系统,它是Windows 95 OSR2及后续版本和Windows NT 4.0中引入的。与早期的FAT16文件系统相比,FAT32的主要优点是支持更大的分区和文件大小。
FAT32的特点包括:
- 更大的分区:FAT32支持的最大分区大小为2TB(尽管实际可用的最大容量可能会因操作系统和其他因素而有所限制)。
- 更大的文件:FAT32支持的最大文件大小为4GB。
- 兼容性:FAT32文件系统在多种操作系统上都是可用的,包括Windows、Linux和macOS。
- 简单的结构:FAT32文件系统的结构相对简单,易于实现和维护。
- 性能:尽管FAT32文件系统在一些方面不如更现代的文件系统(如NTFS或ext4)高效,但在许多常见的用途中,它的性能仍然是足够的。
- 安全性:与更现代的文件系统相比,FAT32在安全性方面可能较弱,因为它不支持一些现代的安全特性,如访问控制列表(ACL)或加密。