操作系统面试高频(六)虚拟地址与页表
1.什么是文件系统?它的作用是什么?⭐
- 存储管理:文件系统负责管理计算机的存储设备,如硬盘、固态硬盘等。它将文件存储在这些设备上,并负责分配和回收存储空间。文件系统通过数据块的分配和索引机制,确保文件能够被快速定位和访问。
- 文件组织:文件系统定义了文件和目录的结构和组织方式。它通过层次化的目录结构或扁平化的文件结构,帮助用户对文件进行分类、分组和管理。文件系统提供了创建、删除、移动和重命名文件和目录的操作,便于用户组织和管理文件。
- 文件访问控制:文件系统提供了对文件的访问权限控制。它允许用户或程序对文件进行读取、写入和执行等操作,并根据用户角色和权限设置文件的访问级别。这样可以保护文件的机密性和完整性,限制未授权的访问和修改。
- 文件操作和管理:文件系统提供了一系列的接口和工具,允许用户对文件进行各种操作和管理。这包括文件的复制、移动、重命名、压缩和解压缩等操作,以及对文件属性的设置和查询,如文件大小、文件类型、创建时间等。
- 文件共享和备份:文件系统支持文件的共享,使多个用户能够同时访问和修改同一个文件。这促进了团队协作和信息共享。此外,文件系统还提供了备份和恢复的功能,确保用户的数据安全和可靠性。
2.说说进程调度算法有哪些?⭐⭐
- 先来先服务(FCFS):按照进程到达的先后顺序进行调度。先到达的进程先被执行,直到该进程完成或被阻塞。
- 短作业优先(SJF):根据进程的执行时间来进行调度,执行时间短的进程先被执行。该算法可以最小化平均等待时间,但可能导致长作业饥饿。
- 最短剩余时间优先(SRTF):在执行过程中,根据剩余执行时间来动态调度进程。如果一个新到达的进程的剩余执行时间比当前进程的剩余执行时间短,则进行切换。
- 优先级调度:为每个进程分配一个优先级,并按照优先级来调度进程。具有较高优先级的进程先被执行,较低优先级的进程可能会被较高优先级的进程长时间抢占。
- 时间片轮转调度(Round Robin):将可用的CPU时间划分为固定大小的时间片(如10ms),每个进程在一个时间片内被执行,然后被放到就绪队列的末尾。这样可以保证每个进程都有机会执行,并提供一种均衡的调度。
- 多级反馈队列调度:将就绪队列划分为多个队列,每个队列具有不同的时间片大小。新到达的进程首先进入第一个队列,如果在该队列执行完后还有剩余时间,则进入下一个队列,以此类推。这个算法可以根据进程的特性分配不同的优先级。
3.简述LRU算法及其实现方式。⭐⭐
LRU(Least Recently Used)算法是一种用于页面置换的算法,用于决定哪些页面应该被置换出内存。这个算法的基本思想是,当需要置换页面时,选择最近最少被使用的页面进行替换。
LRU 算法:
实现 LRU 算法的方式可以利用一个数据结构来记录页面的访问历史,可以使用链表或者队列来实现。下面是一种基于双向链表的 LRU 算法实现方式:
- 维护一个双向链表。链表的头部表示最近使用的页面,尾部表示最久未使用的页面。
- 当访问一个页面时,如果页面在链表中存在,将其从原位置删除,并插入到链表头部。
- 当访问一个页面时,如果页面不在链表中,且缓存未满,则直接将该页面插入到链表头部。
- 当访问一个页面时,如果页面不在链表中,且缓存已满,则删除链表尾部的页面,并将新页面插入到链表头部。
通过这种方式,最近访问的页面会被移到链表头部,而长时间未被访问的页面会逐渐移到链表尾部。当需要置换页面时,只需要淘汰链表尾部的页面即可。
LRU算法的优点是可以充分利用程序的局部性原理,将最近被访问的页面保留在内存中,从而提高缓存命中率和访问效率。但它也存在一些缺点,如实现复杂度较高和需要额外的数据结构来记录页面访问历史等。
代码实现:
#include <iostream> #include <unordered_map> using namespace std; class LRUCache { private: struct ListNode { int key; int value; ListNode* prev; ListNode* next; ListNode(int k, int v) : key(k), value(v), prev(nullptr), next(nullptr) {} }; unordered_map<int, ListNode*> cache; ListNode* head; ListNode* tail; int capacity; public: LRUCache(int capacity) { this->capacity = capacity; head = new ListNode(-1, -1); tail = new ListNode(-1, -1); head->next = tail; tail->prev = head; } void addToHead(ListNode* node) { node->next = head->next; node->prev = head; head->next->prev = node; head->next = node; } void deleteNode(ListNode* node) { node->prev->next = node->next; node->next->prev = node->prev; } int get(int key) { if (cache.count(key)) { ListNode* node = cache[key]; deleteNode(node); addToHead(node); return node->value; } return -1; } void put(int key, int value) { if (cache.count(key)) { ListNode* node = cache[key]; deleteNode(node); node->value = value; addToHead(node); } else { if (cache.size() == capacity) { ListNode* tailNode = tail->prev; deleteNode(tailNode); cache.erase(tailNode->key); delete tailNode; }
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
c++/嵌入式面经专栏 文章被收录于专栏
BG双9,目前在某外企。打算把之前校招时做的笔记通过专栏发出来,本专栏适合于C/C++、嵌入式方向就业的同学,本篇面经总结数千篇面经的知识集合,实时更新全网最新的嵌入式/C++最新内容,囊括了C语言、C++、操作系统、计算机网络、嵌入式、算法与数据结构、数据库等一系列知识点,在我看来这些是求职者在面试中必须掌握的知识点。最后呢祝各位能找到自己合适的工作。。