设备分配用数据结构详解
一、设备管理概述
1.1 设备分类
| 设备类型 | 特点 | 例子 |
|---|---|---|
| 独占设备 | 一段时间内只允许一个进程使用 | 打印机、磁带机 |
| 共享设备 | 多个进程可同时使用 | 磁盘、网卡 |
| 虚拟设备 | 通过虚拟化技术模拟的设备 | SPOOLing系统中的虚拟打印机 |
1.2 设备分配目标
- 提高设备利用率:避免设备空闲
- 保证公平性:避免进程饥饿
- 避免死锁:合理分配资源
- 与设备无关性:用户无需了解设备细节
二、核心数据结构
2.1 系统设备表(SDT - System Device Table)
作用:记录系统中所有设备的基本信息
c
struct SystemDeviceTable {
int device_count; // 系统设备总数
DeviceControlTable* devices[MAX_DEVICES]; // 指向各设备的DCT指针
int free_device_count; // 空闲设备数
// 其他系统级信息...
};
内存中的存储形式:
SDT:
┌─────────────────────┐
│ device_count = 5 │
├─────────────────────┤
│ devices[0] → DCT1 │
│ devices[1] → DCT2 │
│ devices[2] → DCT3 │
│ devices[3] → DCT4 │
│ devices[4] → DCT5 │
├─────────────────────┤
│ free_device_count=3 │
└─────────────────────┘
2.2 设备控制表(DCT - Device Control Table)
作用:每个设备一张,记录设备状态和控制信息
c
struct DeviceControlTable {
// 设备标识信息
char device_id[20]; // 设备标识符
DeviceType type; // 设备类型(字符/块/网络)
DeviceStatus status; // 设备状态(空闲/忙碌/故障)
// 设备连接信息
int controller_id; // 连接的控制器ID
ControllerControlTable* controller; // 指向COCT的指针
int channel_id; // 连接的通道ID
ChannelControlTable* channel; // 指向CHCT的指针
// 设备分配信息
int attached_process; // 当前使用进程ID(-1表示空闲)
Queue* wait_queue; // 等待该设备的进程队列
// 设备特性
int transfer_rate; // 数据传输速率(KB/s)
int block_size; // 块大小(字节)
bool shareable; // 是否可共享
// 状态信息
time_t last_used; // 最后使用时间
int error_count; // 错误计数
// ... 其他设备特定信息
};
DCT示例(打印机):
打印机DCT:
┌─────────────────────┐
│ device_id: "PRN001" │
│ type: CHARACTER │
│ status: BUSY │
├─────────────────────┤
│ controller_id: 3 │
│ channel_id: 1 │
├─────────────────────┤
│ attached_process: 15│
│ wait_queue: [P18,P22]│
├─────────────────────┤
│ transfer_rate: 100 │
│ shareable: FALSE │
└─────────────────────┘
2.3 控制器控制表(COCT - Controller Control Table)
作用:每个控制器一张,管理设备控制器
c
struct ControllerControlTable {
char controller_id[20]; // 控制器标识符
ControllerStatus status; // 控制器状态
DeviceType supported_types; // 支持的设备类型
// 连接信息
int channel_id; // 连接的通道ID
ChannelControlTable* channel; // 指向CHCT
// 设备连接
int connected_devices[MAX_PER_CONTROLLER]; // 连接的设备ID数组
int device_count; // 连接设备数
// 分配信息
int attached_process; // 当前使用进程ID
Queue* wait_queue; // 等待控制器的进程队列
// 控制器特性
int buffer_size; // 缓冲区大小
bool dma_enabled; // 是否支持DMA
// ... 其他控制器特定信息
};
2.4 通道控制表(CHCT - Channel Control Table)
作用:每个通道一张,管理I/O通道
c
struct ChannelControlTable {
char channel_id[20]; // 通道标识符
ChannelType type; // 通道类型(字节多路/数组选择/DMA)
ChannelStatus status; // 通道状态
// 连接信息
int connected_controllers[MAX_PER_CHANNEL]; // 连接的控制器ID
int controller_count; // 连接控制器数
// 分配信息
int attached_process; // 当前使用进程ID
Queue* wait_queue; // 等待通道的进程队列
// 通道特性
int bandwidth; // 带宽(MB/s)
bool interrupt_enabled; // 是否支持中断
// ... 其他通道特定信息
};
2.5 设备分配请求表(DART)
作用:记录进程的设备分配请求
c
struct DeviceAllocationRequest {
int request_id; // 请求ID
int process_id; // 请求进程ID
char device_id[20]; // 请求的设备ID
int controller_id; // 请求的控制器ID
int channel_id; // 请求的通道ID
// 请求参数
int operation_type; // 操作类型(读/写/控制)
int priority; // 请求优先级
time_t request_time; // 请求时间
// 状态信息
RequestStatus status; // 请求状态(等待/分配/完成)
int allocated_device; // 分配的设备ID(-1表示未分配)
time_t allocation_time; // 分配时间
// 链接信息(用于队列)
DeviceAllocationRequest* next; // 下一请求
DeviceAllocationRequest* prev; // 上一请求
};
三、数据结构关系图
3.1 整体关系
进程PCB
↓ (包含设备分配信息)
系统设备表(SDT)
↓ (指向各个设备)
设备控制表(DCT) → 控制器控制表(COCT) → 通道控制表(CHCT)
↓ ↓ ↓
设备队列 控制器队列 通道队列
3.2 数据结构链接示例
c
// 简化的数据结构链接
struct ProcessControlBlock {
int pid;
// ... 其他进程信息
DeviceAllocation* device_allocations; // 进程已分配的设备列表
};
struct DeviceAllocation {
DCT* device; // 分配的设备
COCT* controller; // 分配的控制器
CHCT* channel; // 分配的通道
time_t allocation_time;
DeviceAllocation* next; // 下一个分配
};
四、设备分配算法数据结构
4.1 先来先服务(FCFS)分配
c
// FCFS等待队列
struct FCFSQueue {
DeviceAllocationRequest* front; // 队首
DeviceAllocationRequest* rear; // 队尾
int count; // 等待数量
// 操作方法
void enqueue(DeviceAllocationRequest* request);
DeviceAllocationRequest* dequeue();
DeviceAllocationRequest* peek();
};
4.2 优先级分配
c
// 优先队列(最小堆实现)
struct PriorityQueue {
DeviceAllocationRequest* heap[MAX_REQUESTS];
int size;
// 堆操作方法
void heapify_up(int index);
void heapify_down(int index);
void insert(DeviceAllocationRequest* request);
DeviceAllocationRequest* extract_min();
};
4.3 银行家算法(避免死锁)
c
// 资源分配图
struct ResourceAllocationGraph {
int process_count; // 进程数
int resource_count; // 资源数(设备数)
// 矩阵表示
int allocation[MAX_PROCESSES][MAX_RESOURCES]; // 已分配矩阵
int request[MAX_PROCESSES][MAX_RESOURCES]; // 请求矩阵
int available[MAX_RESOURCES]; // 可用资源向量
int max[MAX_PROCESSES][MAX_RESOURCES]; // 最大需求矩阵
// 安全状态检测
bool is_safe_state();
// 资源分配
bool allocate_resources(int process_id, int resource_id, int units);
// 资源回收
void release_resources(int process_id, int resource_id, int units);
};
五、SPOOLing系统数据结构
5.1 输入井和输出井
c
// 输出井(用于打印机等输出设备)
struct OutputWell {
char well_id[20]; // 井标识符
int total_size; // 总容量
int used_size; // 已用容量
int block_size; // 块大小
// 文件队列
struct {
char filename[50]; // 假脱机文件名
int process_id; // 所属进程
int file_size; // 文件大小
int priority; // 打印优先级
time_t arrival_time; // 到达时间
} files[MAX_SPOOL_FILES];
int file_count; // 文件数量
};
5.2 SPOOLing调度表
c
struct SpoolingScheduleTable {
// 输入井调度
struct {
char device_id[20]; // 输入设备ID
OutputWell* input_well; // 对应的输入井
ProcessQueue* reader_queue; // 读取进程队列
} input_schedule[MAX_INPUT_DEVICES];
// 输出井调度
struct {
char device_id[20]; // 输出设备ID
OutputWell* output_well; // 对应的输出井
ProcessQueue* writer_queue; // 写入进程队列
int current_file_index; // 当前打印文件索引
} output_schedule[MAX_OUTPUT_DEVICES];
// 调度算法
SchedulingAlgorithm algorithm; // 调度算法(FCFS/优先级)
};
六、现代操作系统中的设备管理数据结构
6.1 Linux设备管理(简化版)
c
// Linux设备结构(简化的字符设备)
struct CharDevice {
// 设备标识
dev_t dev; // 设备号(主设备号+次设备号)
char name[64]; // 设备名称
// 操作函数指针
struct file_operations* fops; // 文件操作函数集
// 设备状态
atomic_t open_count; // 打开计数
struct mutex lock; // 互斥锁
wait_queue_head_t wait_queue; // 等待队列
// 设备私有数据
void* private_data;
// 设备列表管理
struct list_head list; // 链表节点
};
// 设备类别
struct DeviceClass {
char name[64]; // 类别名称
struct list_head devices; // 设备链表头
int device_count; // 设备数量
struct kobject* kobj; // 内核对象
};
6.2 Windows设备管理
c
// Windows设备对象(简化的WDM模型)
typedef struct _DEVICE_OBJECT {
// 设备对象头
SHORT Type; // 对象类型
SHORT Size; // 对象大小
// 设备信息
struct _DRIVER_OBJECT* DriverObject; // 驱动对象
struct _DEVICE_OBJECT* NextDevice; // 下一个设备
struct _DEVICE_OBJECT* AttachedDevice; // 附加设备
// 设备特性
ULONG DeviceType; // 设备类型
ULONG Characteristics; // 设备特性
ULONG Flags; // 设备标志
// I/O管理
struct _VPB* Vpb; // 卷参数块
PVOID DeviceExtension; // 设备扩展
// ... 其他Windows特定字段
} DEVICE_OBJECT;
七、设备分配算法实现示例
7.1 设备分配函数
c
// 设备分配主函数
int allocate_device(int process_id,
DeviceRequest* request,
SystemDeviceTable* sdt) {
// 1. 查找合适设备
DCT* device = find_suitable_device(request, sdt);
if (!device) {
add_to_wait_queue(process_id, request);
return WAIT_FOR_DEVICE;
}
// 2. 分配控制器
COCT* controller = allocate_controller(device->controller);
if (!controller) {
return CONTROLLER_BUSY;
}
// 3. 分配通道
CHCT* channel = allocate_channel(controller->channel);
if (!channel) {
release_controller(controller);
return CHANNEL_BUSY;
}
// 4. 更新数据结构
device->status = BUSY;
device->attached_process = process_id;
controller->status = BUSY;
controller->attached_process = process_id;
channel->status = BUSY;
channel->attached_process = process_id;
// 5. 记录分配信息
DeviceAllocation* allocation = create_allocation_record(
process_id, device, controller, channel);
add_to_process_allocation_list(process_id, allocation);
return ALLOCATION_SUCCESS;
}
7.2 设备回收函数
c
void release_device(int process_id, int device_id) {
// 1. 查找分配记录
DeviceAllocation* allocation =
find_allocation(process_id, device_id);
if (!allocation) {
return; // 未找到分配记录
}
// 2. 释放设备
DCT* device = allocation->device;
device->status = IDLE;
device->attached_process = -1;
// 3. 释放控制器(如果无其他设备使用)
if (controller_idle(allocation->controller)) {
allocation->controller->status = IDLE;
allocation->controller->attached_process = -1;
}
// 4. 释放通道(如果无其他控制器使用)
if (channel_idle(allocation->channel)) {
allocation->channel->status = IDLE;
allocation->channel->attached_process = -1;
}
// 5. 检查等待队列,唤醒等待进程
if (!is_empty(device->wait_queue)) {
Process* next_process = dequeue(device->wait_queue);
wakeup_process(next_process);
}
// 6. 删除分配记录
remove_allocation_record(process_id, allocation);
free(allocation);
}
八、数据结构优化技巧
8.1 哈希表加速查找
c
// 设备ID到DCT的哈希映射
struct DeviceHashTable {
struct HashEntry {
char device_id[20];
DCT* device;
struct HashEntry* next;
} *table[HASH_SIZE];
// 哈希函数
int hash_function(char* device_id) {
int hash = 0;
for (int i = 0; device_id[i]; i++) {
hash = (hash * 31 + device_id[i]) % HASH_SIZE;
}
return hash;
}
// 查找设备
DCT* find_device(char* device_id) {
int index = hash_function(device_id);
HashEntry* entry = table[index];
while (entry) {
if (strcmp(entry->device_id, device_id) == 0) {
return entry->device;
}
entry = entry->next;
}
return NULL;
}
};
8.2 位图管理空闲设备
c
// 使用位图高效管理设备状态
struct DeviceBitmap {
unsigned int* bits; // 位数组
int total_devices; // 设备总数
int free_count; // 空闲设备数
// 分配设备
int allocate() {
for (int i = 0; i < (total_devices + 31)/32; i++) {
if (bits[i] != 0xFFFFFFFF) { // 非全1
// 查找第一个0位
int bit = ffs(~bits[i]) - 1; // ffs返回最低位的1的位置
int device_id = i * 32 + bit;
bits[i] |= (1 << bit); // 设置为1(忙碌)
free_count--;
return device_id;
}
}
return -1; // 无空闲设备
}
// 释放设备
void release(int device_id) {
int word = device_id / 32;
int bit = device_id % 32;
bits[word] &= ~(1 << bit); // 设置为0(空闲)
free_count++;
}
};
九、总结要点
9.1 核心数据结构记忆表
| 数据结构 | 缩写 | 作用 | 关键字段 |
|---|---|---|---|
| 系统设备表 | SDT | 管理所有设备 | devices[], free_count |
| 设备控制表 | DCT | 单个设备信息 | status, controller, wait_queue |
| 控制器表 | COCT | 控制器管理 | status, channel, connected_devices |
| 通道控制表 | CHCT | 通道管理 | status, bandwidth, wait_queue |
| 设备分配表 | DART | 记录分配请求 | process_id, device_id, status |
9.2 设备分配流程
- 进程请求 → 2. 查找SDT → 3. 检查DCT → 4. 分配COCT → 5. 分配CHCT → 6. 更新状态 → 7. 返回结果
9.3 设计原则
- 层次化:设备→控制器→通道的层次管理
- 状态记录:准确记录每个资源的状态
- 队列管理:合理处理等待进程
- 死锁避免:使用银行家算法等避免死锁
- 效率优化:使用哈希表、位图等提高效率
这些数据结构共同构成了操作系统中设备管理的核心框架,确保了设备资源的有效分配和管理。