table {
border-collapse: collapse;
width: 100%;
margin-bottom: 1rem;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
pre {
background-color: #f8f8f8;
padding: 15px;
border-radius: 4px;
overflow-x: auto;
}
1、互联网是局域网(LAN)还是广域网(WAN)?
互联网是广域网(WAN),广域网通常连接建筑物、城市或国家,互联网连接了全球范围内的计算机和网络,符合广域网覆盖范围大的特点。
2、资源利用率问题在不同类型的操作系统中以不同形式出现。列出大型机或小型计算机系统中必须谨慎管理的资源。
大型机或小型计算机系统中必须谨慎管理的资源有CPU时间、内存、I/O设备、文件存储空间等。
3、资源利用率问题在不同类型的操作系统中以不同形式出现。列出连接到服务器的工作站中必须谨慎管理的资源。
连接到服务器的工作站中,操作系统需要管理的资源包括:
CPU周期
主内存
文件存储
I/O设备(如打印机、调制解调器、USB存储驱动器等外围设备)
4、资源利用问题在不同类型的操作系统中以不同形式出现。列出手持计算机中必须谨慎管理的资源。
手持计算机资源管理的重要性
手持计算机由于功率、速度和接口的限制,操作系统主要为
个人可用性
而设计,同时
单位电池续航的性能
也很重要。
因此,必须谨慎管理的资源包括:
电池电量
CPU时间
内存空间
文件存储
等常规资源
5、描述对称多处理和非对称多处理之间的区别。多处理器系统的三个优点和一个缺点是什么?
对称多处理与非对称多处理的区别
区别描述
非对称多处理
每个处理器被分配特定任务。
存在一个主处理器,负责控制整个系统。
其他处理器要么听从主处理器的指令,要么有预定义的任务。
存在
主-从关系
。
对称多处理
每个处理器都能执行操作系统内的所有任务。
所有处理器处于对等地位。
不存在主-从关系
。
多处理器系统的优点
1. 提高吞吐量
增加处理器数量可以在更短时间内完成更多工作。
由于合作任务时的开销和对共享资源的竞争,加速比小于处理器数量。
2. 规模经济
多处理器系统的成本低于等效的多个单处理器系统。
可以共享外围设备、大容量存储和电源。
3. 提高可靠性
如果功能能在多个处理器间合理分配,一个处理器故障不会使系统停止。
故障只会使系统变慢,而非完全失效。
多处理器系统的缺点
效率低下
在对称多处理系统中,由于CPU是独立的,可能出现一个CPU闲置而另一个过载的情况。
6、集群系统与多处理器系统有何不同?属于一个集群的两台机器要合作提供高可用性服务需要什么条件?
集群系统与多处理器系统的区别
集群系统与多处理器系统的不同在于:
集群系统
:由两个或多个独立的系统(节点)连接在一起组成。
多处理器系统
:是将多个 CPU 集中在一起完成计算工作。
一般认为,集群计算机具有以下特点:
共享存储
通过局域网(LAN)或更快的互连设备(如 Infiniband)紧密相连
两台属于一个集群的机器要合作提供高可用性服务,需要:
添加一定程度的系统冗余
在集群节点上运行一层集群软件
每个节点可以通过局域网监控其他一个或多个节点。如果被监控的机器出现故障,监控机器可以:
接管其存储
重新启动其功能
此外,一些集群技术中还包含
分布式锁管理器(DLM)
。
7、区分分布式系统的客户端 – 服务器模型和对等(P2P)模型。
在客户端 – 服务器模型中,客户端和服务器有明确区分,服务器是瓶颈。而在对等模型中,系统内所有节点都是对等的,每个节点可根据需求作为客户端或服务器。
客户端 – 服务器系统中,服务由服务器提供;
对等系统中,服务可由网络中多个分布式节点提供。
8、直接内存访问(DMA)用于高速I/O设备,以避免增加CPU的执行负载。当DMA控制器传输数据时,CPU可以执行其他程序。这个过程会干扰用户程序的执行吗?如果会,描述会造成哪些形式的干扰?
当DMA控制器抢占内存总线时,会对用户程序执行产生一定干扰。在DMA控制器占用内存总线期间,CPU暂时无法访问主内存,尽管仍可访问其一级和二级缓存中的数据项,但这种
周期窃取
会减慢CPU的计算速度,从而可能影响正在执行的用户程序,导致用户程序的执行速度变慢。
9、请说明缓存有用的两个原因。它们解决了哪些问题?又引发了哪些问题?如果缓存可以做得和它所缓存的设备一样大(例如,一个和磁盘一样大的缓存),为什么不把它做得那么大并去掉该设备呢?
缓存的作用与影响
缓存有用的两个原因
提高数据访问速度
信息从缓存获取比从原存储系统获取更快。
减少对原存储系统的访问
减轻原存储系统的压力。
解决的问题
减少CPU等待数据的时间,提高系统性能
减少磁盘I/O操作,提高I/O效率
引发的问题
缓存管理是重要设计问题,需谨慎选择缓存大小和替换策略
缓存大小有限,可能出现缓存缺失
不把缓存做得和设备一样大并去掉设备的原因
缓存成本高,做大缓存会大幅增加成本
缓存有易失性,断电数据丢失,不能替代设备长期存储数据
10、描述一种强制实施内存保护的机制,以防止程序修改与其他程序关联的内存。
内存保护的实现方式
可以使用
基址寄存器
和
限长寄存器
来实现内存保护。
基址寄存器
保存最小合法物理内存地址。
限长寄存器
指定地址范围大小。
在用户模式下,CPU硬件会将每个生成的地址与这两个寄存器进行比较:
如果程序试图访问
操作系统内存
或其他
用户内存
,将触发一个
陷阱到操作系统
。
操作系统会将此视为
致命错误
。
特权指令的控制
基址和限长寄存器只能由操作系统使用
特殊的特权指令
加载。
特权指令只能在
内核模式下执行
。
只有操作系统在内核模式下运行,因此:
只有操作系统能加载这两个寄存器
这可以防止用户程序更改其内容。
11、什么样的网络配置最适合宿舍楼层?
局域网(LAN)最适合宿舍楼层,因为局域网可连接一个房间、一层楼或一栋楼内的计算机,能满足宿舍楼层内计算机的通信需求。
12、哪种网络配置最适合一个国家?
广域网(WAN)的应用范围
广域网(WAN)通常最适合一个国家。
广域网可以连接不同的建筑物、城市甚至国家,能满足一个国家内不同地区之间的通信需求。一个跨国公司可能会使用广域网来连接其全球各地的办公室,同理,一个国家也可以利用广域网来实现全国范围内的网络通信。
13、定义网络操作系统的基本特性。
网络操作系统提供如跨网络文件共享等功能,包含允许不同计算机上的不同进程交换消息的通信方案。运行网络操作系统的计算机能独立于网络上的其他计算机运行,不过它知晓网络并能与其他联网计算机通信。
14、掌上电脑固有的权衡是什么?
掌上电脑的优势与限制
优势
便携性
:掌上电脑的最大优势在于其方便和便携。
功能拓展
:随着网络连接的普及,以及新增的如数码相机和MP3播放器等功能,其用途不断拓展。
限制
内存限制
内存容量
:物理内存通常在1MB到1GB之间,远低于普通PC或工作站。
内存管理
:操作系统和应用程序需要高效地管理内存。
处理器性能
处理速度
:处理器速度仅为PC处理器的一小部分。
功耗考虑
:为降低功耗,大多使用更小、更慢的处理器。
设计要求
:操作系统和应用程序的设计不能过度消耗处理器性能。
输入与显示方式
输入方式
:受物理空间限制,多采用小键盘、手写识别或小屏幕键盘。
显示局限
:显示屏较小,带来一定的使用局限。
15、命令解释器的目的是什么?为什么它通常与内核分离?
命令解释器的作用与实现
命令解释器的主要目的是获取并执行用户指定的下一个命令。许多在该层面给出的命令用于操作文件,如创建、删除、列出、打印、复制、执行等。
它通常与内核分离,是因为有些操作系统将命令解释器视为一个特殊程序,在作业启动或用户首次登录(在交互式系统上)时运行。并且像 UNIX 等操作系统通过系统程序实现大多数命令,命令解释器只需用命令识别要加载到内存并执行的文件,这样可使程序员通过创建新文件轻松向系统添加新命令。
16、为了启动一个新进程,命令解释器或 shell 必须执行哪些系统调用?
为了启动一个新进程,shell 需执行
fork()
系统调用创建新进程,再通过
exec()
系统调用将所选程序加载到内存并执行。
17、系统程序的目的是什么?
系统程序与请求处理
系统程序是为了满足许多常见的用户请求。不同层次的请求有所不同:
系统调用层
:需提供基本功能,如:
进程控制
文件操作
设备操作
更高级别的请求
:由命令解释器或系统程序处理,并转化为一系列系统调用。
系统服务分类
系统服务可分为以下类别:
程序控制
状态请求
I/O 请求
18、列出操作系统提供的五项服务,并解释每项服务如何为用户带来便利。在哪些情况下,用户级程序无法提供这些服务?请解释你的答案。
操作系统提供的五项服务及其为用户带来的便利
操作系统提供的五项服务:
用户界面
提供命令行、批处理、图形用户界面等多种形式,方便用户与系统交互。
程序执行
能将程序加载到内存并运行,还能正常或异常结束程序,让用户方便运行程序。
I/O 操作
为用户提供进行 I/O 操作的手段,因用户通常无法直接控制 I/O 设备,操作系统的介入保障了效率和保护。
文件系统操作
方便程序读写、创建、删除文件和目录,搜索文件、列出文件信息以及管理文件权限。
通信
支持进程间信息交换,无论是同一计算机内还是不同计算机系统间。
在某些情况下用户级程序无法提供这些服务:
I/O 操作
用户通常不能直接控制 I/O 设备,操作系统需要对设备进行管理和调度,以确保效率和保护,用户级程序难以做到。
资源分配
当有多个用户或作业同时运行时,操作系统要根据多种因素对不同资源进行合理分配,用户级程序不具备统筹分配系统资源的能力。
保护和安全
操作系统要确保所有对系统资源的访问受到控制,防止进程间相互干扰,并保障系统免受外部攻击,用户级程序难以实现如此全面的系统安全保护。
19、为什么策略和机制的分离是可取的?
策略与机制分离的优势
策略和机制分离可取的原因在于,策略可能会随地点或时间变化。若不分离,每次策略改变都需更改底层机制;而分离后,策略改变只需重新定义系统的某些参数。
如合适分离机制与策略,一个机制可支持不同策略决策。微内核操作系统通过实现基本的原语构建块,将策略和机制分离到极致,允许通过用户创建的内核模块或用户程序添加更高级的机制和策略。
此外,将调度机制通用化,可通过单一加载新表命令实现巨大的策略更改。
20、微内核方法进行系统设计的主要优点是什么?在微内核架构中,用户程序和系统服务如何交互?微内核方法的缺点是什么?
微内核方法的特点
主要优点:
易于扩展操作系统
新服务添加到用户空间,无需修改内核;修改内核时改动较少。
便于移植
操作系统更易于从一种硬件设计移植到另一种硬件设计。
更高的安全性和可靠性
多数服务以用户进程而非内核进程运行,一个服务失败不影响其他部分。
架构示例:
在微内核架构中,如
Tru64 UNIX 的 Mach 内核
,将 UNIX 系统调用映射为消息传递给适当的用户级服务。
缺点:
性能下降
可能因系统功能开销增加而导致性能下降。例如,
Windows NT
最初的分层微内核组织版本性能低于
Windows 95
。
21、对于操作系统设计者来说,使用虚拟机架构的主要优势是什么?对于用户来说,主要优势是什么?
虚拟机架构的优势
对于操作系统设计者
系统开发便捷化
:可在虚拟机上进行系统开发,而非物理机,减少对正常系统操作的干扰。
实现系统整合
:可在一台物理系统上运行多个独立系统,优化资源使用。
改进应用部署方式
:应用开发者可将应用预安装在虚拟机的定制操作系统中,便于管理和技术支持,但需统一虚拟机格式。
对于用户
多环境运行
:开发者可在工作站同时运行多个操作系统,便于在不同环境中快速移植和测试程序。
高效测试
:质量保证工程师可在多个环境中测试应用,无需为每个环境购买、供电和维护计算机。
22、描述短期调度、中期调度和长期调度之间的差异。
调度器类型与功能
短期调度(CPU调度器)
执行频率
:频繁执行,通常至少每100毫秒执行一次
主要任务
:为CPU选择新进程
执行间隔
:短
性能要求
:必须快速,以减少调度工作对CPU的占用
长期调度(作业调度器)
执行频率
:低,可能数分钟才创建一个新进程
主要任务
:控制内存中的多道程序度
功能
:从进程池中选择进程并加载到内存执行
决策时间
:较充裕,有更多时间决定选择哪个进程执行
注意事项
:需谨慎选择I/O密集型和CPU密集型进程的组合
中期调度
应用场景
:一些操作系统(如分时系统)引入的中间调度级别
核心思想
:将进程从内存中移除(换出),以减少多道程序度
后续操作
:将进程重新引入内存(换入)并继续执行
过程名称
:交换
目的
:改善进程组合或释放内存
23、构建一个进程树。在UNIX或Linux系统上,使用命令获取进程信息,使用命令man ps来获取有关ps命令的更多信息;在Windows系统上,使用任务管理器获取进程信息。
构建进程树的步骤如下:
对于UNIX或Linux系统,使用命令
ps -ael
获取进程信息,使用
man ps
了解
ps
命令的更多信息。
对于Windows系统,使用任务管理器获取进程信息。然后根据这些信息构建进程树。
24、修改日期服务器,使其发送随机笑话而不是当前日期。允许笑话包含多行,客户端代码可用于读取服务器返回的多行笑话。
以下是修改后的 Java 代码示例,实现了一个能发送随机笑话的服务器:
import java.net.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class JokeServer {
// 存储笑话的列表
private static List<String> jokes = new ArrayList<>();
// 随机数生成器
private static Random random = new Random();
static {
// 添加一些笑话到列表中,可自行添加更多
jokes.add("为什么蚕宝宝很有钱?因为它会结茧(节俭)。");
jokes.add("小王剪了个中分,变成了小全。");
jokes.add("有一天小蚂蚁迷路找不到蚁窝,可着急了,恰好看到它的朋友经过,于是冲过去大喊一声:“哥们儿!你…你都如何回蚁窝(回忆我)?”那朋友一愣,然后反问道:“带…带…带着笑或是很沉默?”");
}
public static void main(String[] args) {
try {
// 创建一个服务器套接字,监听端口 6013
ServerSocket sock = new ServerSocket(6013);
// 持续监听连接请求
while (true) {
// 接受客户端的连接
Socket client = sock.accept();
// 创建一个 PrintWriter 对象,用于向客户端发送数据
PrintWriter pout = new PrintWriter(client.getOutputStream(), true);
// 随机选择一个笑话
String joke = jokes.get(random.nextInt(jokes.size()));
// 将笑话发送给客户端
pout.println(joke);
// 关闭客户端套接字
client.close();
}
} catch (IOException ioe) {
// 捕获并打印异常信息
System.err.println(ioe);
}
}
}
代码说明:
jokes
列表
:用于存储多个笑话,你可以根据需要添加更多的笑话。
random
对象
:用于随机选择一个笑话。
static
代码块
:在类加载时初始化笑话列表。
main
方法
:
– 创建一个
ServerSocket
并监听端口 6013。
– 使用
while (true)
循环持续监听客户端连接。
– 接受客户端连接后,随机选择一个笑话并通过
PrintWriter
发送给客户端。
– 关闭客户端套接字,继续监听下一个连接。
这样,客户端就可以使用相应的客户端代码来接收并显示随机笑话了。
25、编写一个使用POSIX共享内存的程序,实现父进程和子进程协作生成并输出斐波那契数列。程序首先要定义一个共享内存的数据结构,该结构包含一个大小为MAX_SEQUENCE的固定大小数组用于存储斐波那契数列的值,以及子进程要生成的数列的大小(数列大小 ≤ MAX_SEQUENCE)。父进程需接受命令行传递的参数,进行错误检查确保参数 ≤ MAX_SEQUENCE,然后创建共享内存段、附加到自身地址空间、设置数列大小、创建子进程并等待其完成、输出共享内存中的斐波那契数列,最后分离并移除共享内存段。子进程将斐波那契数列写入共享内存后分离该段。同时,父进程和子进程要使用wait()系统调用进行同步,保证父进程在子进程完成数列生成后再输出。已知#define MAX_SEQUENCE 10 typedef struct { long fib_sequence[MAX_SEQUENCE]; int sequence_size; } shared_data; 请描述该程序的主要实现步骤。
该程序主要实现步骤如下:
定义共享内存的数据结构,包含存储斐波那契数列的固定大小数组和数列大小。
父进程的操作步骤:
– 接受参数
– 创建和附加共享内存段
– 设置数列大小
– 创建子进程并等待其完成
– 输出数列
– 分离和移除共享内存段
子进程将斐波那契数列写入共享内存并分离该段。
父进程和子进程使用
wait()
系统调用进行同步,确保父进程在子进程完成数列生成后再输出。
26、编写一个C程序,该程序接收一个共享内存段的标识符。此程序将调用shmctl()函数来获取其shm_ds结构。然后,它将输出该共享内存段的以下值:段ID、键、模式、所有者用户ID、大小、连接次数。
以下是实现该功能的C程序示例:
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <segment_id>
", argv[0]);
return 1;
}
int segment_id = atoi(argv[1]);
struct shmid_ds shmbuffer;
if (shmctl(segment_id, IPC_STAT, &shmbuffer) == -1) {
perror("shmctl");
return 1;
}
printf("Segment ID: %d
", segment_id);
printf("Key: %ld
", (long)shmbuffer.shm_perm.__key);
printf("Mode: %o
", shmbuffer.shm_perm.mode);
printf("Owner UID: %d
", shmbuffer.shm_perm.uid);
printf("Size: %lu bytes
", (unsigned long)shmbuffer.shm_segsz);
printf("Number of attaches: %d
", shmbuffer.shm_nattch);
return 0;
}
该程序接收一个命令行参数作为共享内存段的标识符,调用
shmctl()
函数获取
shmid_ds
结构,并输出所需的信息。
27、在多线程进程中,以下哪些程序状态组件是线程间共享的?a. 寄存器值 b. 堆内存 c. 全局变量 d. 栈内存
b、c
28、Linux不区分进程和线程,以相同的方式处理它们,根据传递给clone()系统调用的标志集,使一个任务更类似于进程或线程。然而,许多操作系统(如Windows和Solaris)对进程和线程的处理方式不同,通常采用一种表示法,其中进程的数据结构包含指向属于该进程的各个线程的指针。对比内核中这两种对进程和线程进行建模的方法。
操作系统中的进程与线程处理方式
Linux
将进程和线程统一视为任务
通过
clone()
系统调用的标志集决定父子任务的资源共享程度
若设置某些标志:
父子任务共享资源
类似创建线程
若不设置标志:
不共享资源
功能类似
fork()
系统调用
Windows 和 Solaris 等操作系统
明确区分进程和线程
进程的数据结构包含指向所属线程的指针
进程和线程有清晰的界限
29、编写一个基于套接字的日期服务器,使服务器在单独的线程中处理每个客户端请求。
以下是修改后的代码,让服务器在单独的线程中处理每个客户端请求:
import java.net.*;
import java.io.*;
import java.util.Date;
// 处理客户端请求的线程类
class ClientHandler extends Thread {
private Socket client;
public ClientHandler(Socket client) {
this.client = client;
}
@Override
public void run() {
try {
PrintWriter pout = new PrintWriter(client.getOutputStream(), true);
// 向套接字写入日期
pout.println(new Date().toString());
// 关闭套接字
client.close();
} catch (IOException ioe) {
System.err.println(ioe);
}
}
}
// 日期服务器类
public class DateServer {
public static void main(String[] args) {
try {
// 创建 ServerSocket 监听端口 6013
ServerSocket sock = new ServerSocket(6013);
// 开始监听连接
while (true) {
// 接受客户端连接
Socket client = sock.accept();
// 创建新线程处理客户端请求
ClientHandler handler = new ClientHandler(client);
handler.start();
}
} catch (IOException ioe) {
System.err.println(ioe);
}
}
}
上述代码中,定义了一个
ClientHandler
类,它继承自
Thread
类,用于处理每个客户端的请求。在
DateServer
类的
main
方法中,当接收到客户端连接时,会创建一个
ClientHandler
线程实例并启动它,这样每个客户端请求就会在单独的线程中处理。