操作系统基础概念

操作系统(Operating System, OS)是计算机系统中最核心的系统软件,它充当硬件与用户之间的桥梁。操作系统的主要功能是管理计算机的硬件资源,并为应用程序提供运行环境。

操作系统的定义与作用

操作系统可以被定义为:

  • 一组控制和管理计算机硬件与软件资源的程序
  • 合理组织计算机工作流程的接口
  • 为用户提供友好交互界面的软件系统

操作系统的作用主要体现在三个方面:

  1. 资源管理者:管理CPU、内存、磁盘、I/O设备等硬件资源
  2. 运行平台:为应用程序提供执行环境和系统调用接口
  3. 用户界面:提供命令行界面(CLI)或图形用户界面(GUI)

操作系统的发展历程

操作系统经历了几个重要发展阶段:

1. 手工操作阶段(1940s-1950s)

  • 程序员直接在机器语言层面操作计算机
  • 没有操作系统概念
  • 资源利用率极低

2. 单道批处理系统(1950s-11960s)

  • 引入作业控制语言(JCL)
  • 自动依次处理作业队列
  • 仍然存在CPU空闲问题

3. 多道批处理系统(1960s-1970s)

  • 允许多个程序同时驻留在内存中
  • CPU在程序间切换,提高利用率
  • 代表性系统:IBM OS/360

4. 分时系统(1970s)

  • 将CPU时间划分为时间片
  • 多用户通过终端同时使用计算机
  • 代表性系统:UNIX

5. 现代操作系统(1980s至今)

  • 图形用户界面普及
  • 网络功能集成
  • 多核处理器支持
  • 移动操作系统兴起

操作系统的基本特性

现代操作系统具有四个基本特性:

1. 并发性(Concurrency)

  • 指两个或多个事件在同一时间间隔内发生
  • 在多道程序环境下,宏观上同时运行,微观上交替执行
  • 与并行(Parallelism)的区别:并行指在同一时刻发生

2. 共享性(Sharing)

  • 系统资源被多个并发进程共同使用
  • 互斥共享(如打印机)和同时访问(如磁盘文件)两种方式

3. 虚拟性(Virtualization)

  • 通过技术手段将物理资源转化为逻辑资源
  • 例如:虚拟内存、虚拟处理器

4. 异步性(Asynchronism)

  • 进程执行顺序和执行时间不确定
  • 但运行结果必须是可再现的

操作系统的体系结构

1. 宏内核(Monolithic Kernel)

  • 所有核心功能都在内核空间实现
  • 优点:性能高
  • 缺点:代码复杂,难以维护
  • 例子:Linux、UNIX

2. 微内核(Microkernel)

  • 只保留最基本的功能(进程管理、内存管理、IPC)
  • 其他功能作为用户态服务运行
  • 优点:结构清晰,易于维护
  • 缺点:性能开销较大
  • 例子:MINIX、QNX

3. 混合内核(Hybrid Kernel)

  • 结合宏内核和微内核的优点
  • 例子:Windows NT

4. 外核(Exokernel)

  • 提供最小化的抽象层
  • 应用程序直接管理资源
  • 主要用于研究领域

进程管理

进程是操作系统中最重要的概念之一,进程管理是操作系统的核心功能。

进程的基本概念

进程的定义

  • 进程是程序的一次执行实例
  • 进程是资源分配和调度的基本单位
  • 进程由程序段、数据段和进程控制块(PCB)组成

进程与程序的区别

  • 程序是静态的代码文件,进程是动态的执行实体
  • 程序可以长期保存,进程有生命周期
  • 一个程序可以对应多个进程(如多个浏览器窗口)
  • 一个进程只能对应一个程序

进程的状态与转换

进程在其生命周期内会经历以下状态:

1. 就绪状态(Ready)

  • 进程已获得除CPU之外的所有必要资源
  • 只要获得CPU就可以立即执行

2. 执行状态(Running)

  • 进程获得CPU,正在执行
  • 单处理器系统中只有一个进程处于此状态

3. 阻塞状态(Blocked)

  • 进程因等待某事件(如I/O完成)而暂停执行
  • 即使CPU空闲,该进程也不能执行

4. 创建状态(New)

  • 进程正在被创建,尚未完成初始化

5. 终止状态(Terminated)

  • 进程执行完毕或被强制终止

状态转换图

创建 → 就绪 ↔ 执行 → 终止
          ↓   ↑
          阻塞

进程控制块(PCB)

PCB是操作系统用于管理进程的核心数据结构,包含以下信息:

1. 进程标识信息

  • 进程ID(PID)
  • 父进程ID(PPID)
  • 用户ID(UID)
  • 组ID(GID)

2. 处理器状态信息

  • 通用寄存器值
  • 程序计数器(PC)
  • 然志寄存器(PSW)
  • 栈指针

3. 进程调度信息

  • 进程状态
  • 优先级
  • 调度队列指针
  • 调度参数

4. 进程控制信息

  • 程序和数据的内存地址
  • 文件描述符表
  • 进程间通信信息
  • 资源使用情况

进程控制

操作系统通过系统调用提供进程控制功能:

1. 进程创建

#include <unistd.h>
pid_t fork(void);

// 示例:创建子进程
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

int main() {
    pid_t pid = fork();
    
    if (pid < 0) {
        // 创建失败
        perror("fork failed");
        return 1;
    } else if (pid == 0) {
        // 子进程
        printf("这是子进程,PID: %d\n", getpid());
        return 0;
    } else {
        // 父进程
        printf("这是父进程,PID: %d, 子进程PID: %d\n", getpid(), pid);
        wait(NULL);  // 等待子进程结束
        return 0;
    }
}

2. 进程终止

#include <stdlib.h>
void exit(int status);

// 正常终止
exit(0);

// 立即终止
_exit(0);

3. 进程等待

#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);

// 示例:等待特定子进程
int main() {
    pid_t pid = fork();
    
    if (pid == 0) {
        // 子进程
        sleep(2);
        printf("子进程完成\n");
        exit(0);
    } else {
        // 父进程
        int status;
        pid_t child = waitpid(pid, &status, 0);
        if (WIFEXITED(status)) {
            printf("子进程%d正常退出,退出码:%d\n", child, WEXITSTATUS(status));
        }
        return 0;
    }
}

4. 进程执行

#include <unistd.h>
int execl(const char *path, const char *arg, ...);
int execv(const char *path, char *const argv[]);

// 示例:执行外部程序
int main() {
    pid_t pid = fork();
    
    if (pid == 0) {
        // 子进程执行ls命令
        execl("/bin/ls", "ls", "-l", NULL);
        // 如果exec成功,下面代码不会执行
        perror("exec failed");
        exit(1);
    } else {
        wait(NULL);
        return 0;
    }
}

进程间通信(IPC)

进程间通信的主要方式:

1. 管道(Pipe)

#include <unistd.h>
int pipe(int pipefd[2]);

// 示例:父子进程通过管道通信
int main() {
    int fd[2];
    if (pipe(fd) == -1) {
        perror("pipe");
        return 1;
    }
    
    pid_t pid = fork();
    
    if (pid == 0) {
        // 子进程:写入数据
        close(fd[0]);  // 关闭读端
        char msg[] = "Hello from child!";
        write(fd[1], msg, sizeof(msg));
        close(fd[1]);
    } else {
        // 父进程:读取数据
        close(fd[1]);  // 关闭写端
        char buffer[128];
        int n = read(fd[0], buffer, sizeof(buffer));
        buffer[n] = '\0';
        printf("父进程收到: %s\n", buffer);
        close(fd[0]);
        wait(NULL);
    }
    return 0;
}

2. 消息队列

#include <sys/msg.h>
#include <sys/ipc.h>

// 消息结构
struct msgbuf {
    long mtype;       // 消息类型
    char mtext[100];  // 消息内容
};

// 创建/获取消息队列
int msgid = msgget(IPC_PRIVATE, 0666);

// 发送消息
struct msgbuf msg = {1, "Hello"};
 msgsnd(msgid, &msg, sizeof(msg.mtext), 0);

// 接收消息
msgrcv(msgid, &msg, sizeof(msg.mtext), 1, 0);

3. 共享内存

#include <sys/shm.h>
#include <sys/ipc.h>

// 创建共享内存
int shmid = shmget(IPC_PRIVATE, 1024, 0666);
char *shared = (char*)shmat(shmid, NULL, 0);

// 使用共享内存
strcpy(shared, "Shared data");

// 分离共享内存
shmdt(shared);
// 删除共享内存
shmctl(shmid, IPC_RMID, NULL);

4. 信号量

#include <sys/sem.h>

// 创建信号量集
int semid = semget(IPC_PRIVATE, 1, 0666);

// P操作(等待)
struct sembuf p = {0, -1, 0};
semop(semid, &p, 1);

// V操作(释放)
struct sembuf v = {0, 1, 0};
semop(semid, &v, 1);

5. 信号(Signal)

#include <signal.h>
#include <stdio.h>
#include <unistd.h>

void handler(int signum) {
    printf("捕获信号: %d\n", signum);
}

int main() {
    // 注册信号处理函数
    signal(SIGINT, handler);
    
    printf("按Ctrl+C测试信号处理\n");
    while(1) {
        sleep(1);
    }
    return 0;
}

进程调度

进程调度算法的目标:

  • CPU利用率最大化
  • 公平性
  • 响应时间最小化
  • 周转时间最小化
  • 吞吐量最大化

1. 先来先服务(FCFS)

# FCFS调度算法示例
def fcfs(processes):
    # processes: [(到达时间, 执行时间, 进程名)]
    processes.sort(key=lambda x: x[0])  # 按到达时间排序
    
    current_time = 0
    results = []
    
    for arrival, burst, name in processes:
        if current_time < arrival:
            current_time = arrival
        start_time = current_time
        finish_time = start_time + burst
        waiting_time = start_time - arrival
        turnaround_time = finish_time - arrival
        
        results.append({
            'name': name,
            'arrival': arrival,
            'burst': burst,
            'start': start_time,
            'finish': finish_time,
            'waiting': waiting_time,
            'turnaround': turnaround_time
        })
        current_time = finish_time
    
    return results

# 测试
processes = [(0, 7, 'P1'), (2, 4, 'P2'), (4, 1, 'P3')]
results = fcfs(processes)
for r in results:
    print(f"{r['name']}: 等待={r['waiting']}, 周转={r['turnaround']}")

2. 短作业优先(SJF)

def sjf(processes):
    # 非抢占式SJF
    processes = sorted(processes, key=lambda x: x[0])  # 按到达时间排序
    ready_queue = []
    current_time = 0
    results = []
    completed = 0
    
    while completed < len(processes):
        # 添加到达的进程到就绪队列
        for p in processes:
            if p[0] <= current_time and p not in ready_queue and p not in [r[0] for r in results]:
                ready_queue.append(p)
        
        if not ready_queue:
            current_time = min([p[0] for p in processes if p not in [r[0] for r in results]])
            continue
        
        # 选择最短作业
        ready_queue.sort(key=lambda x: x[1])
        current = ready_queue.pop(0)
        
        start_time = current_time
        finish_time = start_time + current[1]
        waiting_time = start_time - current[0]
        turnaround_time = finish_time - current[0]
        
        results.append((current, {
            'name': current[2],
            'waiting': waiting_time,
            'turnaround': turnaround_time
        }))
        
        current_time = finish_time
        completed += 1
    
    return results

3. 时间片轮转(RR)

def rr(processes, time_quantum):
    # processes: [(到达时间, 执行时间, 进程名)]
    from collections import deque
    
    processes = sorted(processes, key=lambda x: x[0])
    queue = deque()
    current_time = 0
    results = {}
    remaining = {p[2]: p[1] for p in processes}
    completed = 0
    
    i = 0
    while completed < len(processes):
        # 添加新到达的进程
        while i < len(processes) and processes[i][0] <= current_time:
            queue.append(processes[i])
            i += 1
        
        if not queue:
            current_time = processes[i][0]
            continue
        
        current = queue.popleft()
        name = current[2]
        
        if remaining[name] > time_quantum:
            # 执行一个时间片
            current_time += time_quantum
            remaining[name] -= time_quantum
            
            # 添加新到达的进程
            while i < len(processes) and processes[i][0] <= current_time:
                queue.append(processes[i])
                i += 1
            
            queue.append(current)
        else:
            # 完成执行
            current_time += remaining[name]
            remaining[name] = 0
            results[name] = {
                'finish': current_time,
                'turnaround': current_time - current[0],
                'waiting': current_time - current[0] - current[1]
            }
            completed += 1
    
    return results

4. 优先级调度

def priority_scheduling(processes):
    # 非抢占式优先级调度
    # processes: [(到达时间, 执行时间, 优先级, 进程名)]
    processes = sorted(processes, key=lambda x: x[0])
    ready_queue = []
    current_time = 0
    results = []
    completed = 0
    
    while completed < len(processes):
        # 添加到达的进程
        for p in processes:
            if p[0] <= current_time and p not in ready_queue and p not in [r[0] for r in results]:
                ready_queue.append(p)
        
        if not ready_queue:
            current_time = min([p[0] for p in processes if p not in [r[0] for r in results]])
            continue
        
        # 选择优先级最高的(数值越小优先级越高)
        ready_queue.sort(key=lambda x: x[2])
        current = ready_queue.pop(0)
        
        start_time = current_time
        finish_time = start_time + current[1]
        waiting_time = start_time - current[0]
        turnaround_time = finish_time - current[0]
        
        results.append((current, {
            'name': current[3],
            'waiting': waiting_time,
            'turnaround': turnaround_time
        }))
        
        current_time = finish_time
        completed += 1
    
    return results

5. 多级反馈队列(MLFQ)

def mlfq(processes, time_quantums=[2, 4, 8]):
    # 多级反馈队列
    # processes: [(到达时间, 执行时间, 进程名)]
    from collections import deque
    
    queues = [deque() for _ in range(len(time_quantums))]
    current_time = 0
    results = {}
    remaining = {p[2]: p[1] for p in processes}
    current_queue = 0
    completed = 0
    i = 0
    
    while completed < len(processes):
        # 添加新到达的进程到最高优先级队列
        while i < len(processes) and processes[i][0] <= current_time:
            queues[0].append(processes[i])
            i += 1
        
        # 找到非空队列
        current_queue = 0
        while current_queue < len(queues) and not queues[current_queue]:
            current_queue += 1
        
        if current_queue >= len(queues):
            if i < len(processes):
                current_time = processes[i][0]
            else:
                break
            continue
        
        current = queues[current_queue].popleft()
        name = current[2]
        tq = time_quantums[current_queue]
        
        if remaining[name] > tq:
            # 执行一个时间片
            current_time += tq
            remaining[name] -= tq
            
            # 添加新到达的进程
            while i < len(processes) and processes[i][0] <= current_time:
                queues[0].append(processes[i])
                i += 1
            
            # 降级到下一级队列
            next_queue = min(current_queue + 1, len(queues) - 1)
            queues[next_queue].append(current)
        else:
            # 完成执行
            current_time += remaining[name]
            remaining[name] = 0
            results[name] = {
                'finish': current_time,
                'turnaround': current_time - current[0],
                'waiting': current_time - current[0] - current[1]
            }
            completed += 1
    
    return results

内存管理

内存管理是操作系统的核心功能之一,负责管理计算机的主存储器资源。

内存管理的基本概念

内存管理的目标

  • 内存分配与回收
  • 地址转换与重定位
  • 内存保护与共享
  • 内存扩充

地址空间

  • 逻辑地址(虚拟地址):程序看到的地址空间
  • 物理地址:内存硬件的实际地址
  • 地址转换:将逻辑地址转换为物理地址

连续内存分配

1. 单一连续分配

  • 内存分为系统区和用户区
  • 仅支持单道程序
  • 实现简单,但资源利用率低

2. 固定分区分配

  • 将内存划分为若干固定大小的分区
  • 每个分区只能装入一道作业
  • 存在内部碎片(分区内部未使用的空间)

3. 动态分区分配

  • 根据进程实际需求动态划分内存
  • 常用算法:
    • 首次适应(First Fit)
    • 最佳适应(Best Fit)
    • 最坏适应(Worst Fit)
// 动态分区分配的首次适应算法示例
#include <stdio.h>
#include <stdlib.h>

typedef struct Block {
    int size;
    int start;
    int allocated;
    struct Block *next;
} Block;

Block* create_memory(int size) {
    Block *mem = (Block*)malloc(sizeof(Block));
    mem->size = size;
    mem->start = 0;
    mem->allocated = 0;
    mem->next = NULL;
    return mem;
}

void* first_fit(Block *memory, int size) {
    Block *current = memory;
    while (current != NULL) {
        if (!current->allocated && current->size >= size) {
            // 分裂块
            if (current->size > size) {
                Block *new_block = (Block*)malloc(sizeof(Block));
                new_block->size = current->size - size;
                new_block->start = current->start + size;
                new_block->allocated = 0;
                new_block->next = current->next;
                current->next = new_block;
            }
            current->size = size;
            current->allocated = 1;
            return (void*)(current->start);
        }
        current = current->next;
    }
    return NULL;
}

void deallocate(Block *memory, void *addr) {
    int target_start = (int)addr;
    Block *current = memory;
    Block *prev = NULL;
    
    while (current != NULL) {
        if (current->start == target_start && current->allocated) {
            current->allocated = 0;
            
            // 合并相邻空闲块
            if (current->next && !current->next->allocated) {
                current->size += current->next->size;
                Block *temp = current->next;
                current->next = temp->next;
                free(temp);
            }
            
            if (prev && !prev->allocated) {
                prev->size += current->size;
                prev->next = current->next;
                free(current);
            }
            return;
        }
        prev = current;
        current = current->next;
    }
}

分页存储管理

基本概念

  • 将物理内存划分为固定大小的块,称为页框(Frame)
  • 将逻辑地址空间划分为同样大小的块,称为页(Page)
  • 通过页表实现逻辑地址到物理地址的映射

页表结构

逻辑地址:[页号 | 页内偏移]
    ↓
页表:[页号 → 页框号]
    ↓
物理地址:[页框号 | 页内偏移]

多级页表

// 二级页表示例
#define PAGE_SIZE 4096
#define PAGE_TABLE_SIZE 1024
#define OFFSET_BITS 12
#define PAGE_BITS 10

// 页表项结构
typedef struct {
    unsigned int frame : 20;  // 页框号
    unsigned int valid : 1;   // 有效位
    unsigned int dirty : 1;   // 脏位
    unsigned int accessed : 1; // 访问位
} PageTableEntry;

// 二级页表
typedef struct {
    PageTableEntry **entries;  // 指向一级页表的指针数组
} PageDirectory;

// 地址转换函数
unsigned int translate_address(PageDirectory *dir, unsigned int virtual_addr) {
    unsigned int page_dir_index = (virtual_addr >> (PAGE_BITS + OFFSET_BITS)) & 0x3FF;
    unsigned int page_table_index = (virtual_addr >> OFFSET_BITS) & 0x3FF;
    unsigned int offset = virtual_addr & 0xFFF;
    
    if (!dir->entries[page_dir_index] || 
        !dir->entries[page_dir_index][page_table_index].valid) {
        return -1;  // 页错误
    }
    
    unsigned int frame = dir->entries[page_dir_index][page_table_index].frame;
    return (frame << OFFSET_BITS) | offset;
}

分段存储管理

基本概念

  • 按程序的逻辑结构划分内存
  • 每个段有特定含义(代码段、数据段、栈段等)
  • 支持共享和保护

段表结构

逻辑地址:[段号 | 段内偏移]
    ↓
段表:[段号 → 段基址, 段限长]
    ↓
物理地址:[段基址 + 段内偏移](需检查是否越界)

段页式存储管理

结合分段和分页的优点:

  • 先分段,段内再分页
  • 逻辑地址:[段号 | 段内页号 | 页内偏移]
  • 需要段表和页表两级映射

虚拟内存

基本概念

  • 逻辑地址空间远大于物理内存
  • 程序运行时,只将当前需要的部分装入内存
  • 其余部分保存在磁盘的交换区(Swap)

虚拟内存的实现

  1. 请求调页:访问未装入内存的页时触发缺页中断
  2. 页面置换:当内存不足时,选择页面换出
  3. 页面共享:多个进程共享只读页面

缺页中断处理流程

// 伪代码:缺页中断处理
void page_fault_handler(unsigned int virtual_addr) {
    // 1. 获取页表项
    PageTableEntry *pte = get_page_table_entry(virtual_addr);
    
    if (!pte->valid) {
        // 2. 检查访问权限
        if (!check_permission(virtual_addr)) {
            kill_process();  // 访问违规
            return;
        }
        
        // 3. 分配物理页框
        unsigned int frame = allocate_frame();
        if (frame == -1) {
            // 4. 页面置换
            frame = swap_out();
        }
        
        // 5. 从磁盘读取页面
        read_from_disk(pte->disk_location, frame);
        
        // 6. 更新页表
        pte->frame = frame;
        pte->valid = 1;
        pte->accessed = 1;
    }
    
    // 7. 重新执行指令
    resume_execution();
}

页面置换算法

1. 最佳置换(OPT)

def opt(page_references, frame_count):
    # 理想算法,实际无法实现
    # 选择未来最长时间不会被访问的页面替换
    frames = []
    faults = 0
    
    for i, page in enumerate(page_references):
        if page not in frames:
            if len(frames) < frame_count:
                frames.append(page)
            else:
                # 找到未来最远使用的页面
                future_use = {}
                for f in frames:
                    try:
                        future_use[f] = page_references[i:].index(f)
                    except ValueError:
                        future_use[f] = float('inf')
                
                to_replace = max(future_use, key=future_use.get)
                frames[frames.index(to_replace)] = page
            faults += 1
    
    return faults

2. 先进先出(FIFO)

def fifo(page_references, frame_count):
    from collections import deque
    
    frames = deque(maxlen=frame_count)
    faults = 0
    
    for page in page_references:
        if page not in frames:
            frames.append(page)
            faults += 1
    
    return faults

3. 最近最少使用(LRU)

def lru(page_references, frame_count):
    from collections import OrderedDict
    
    frames = OrderedDict()
    faults = 0
    
    for page in page_references:
        if page in frames:
            # 访问过,移到末尾
            frames.move_to_end(page)
        else:
            if len(frames) < frame_count:
                frames[page] = True
            else:
                # 弹出最久未使用的(第一个)
                frames.popitem(last=False)
                frames[page] = True
            faults += 1
    
    return faults

4. 时钟算法(Clock)

def clock(page_references, frame_count):
    frames = []
    reference_bits = []
    pointer = 0
    faults = 0
    
    for page in page_references:
        if page in frames:
            # 设置引用位
            idx = frames.index(page)
            reference_bits[idx] = 1
        else:
            if len(frames) < frame_count:
                frames.append(page)
                reference_bits.append(1)
            else:
                # 查找引用位为0的页面
                while reference_bits[pointer] == 1:
                    reference_bits[pointer] = 0
                    pointer = (pointer + 1) % frame_count
                
                frames[pointer] = page
                reference_bits[pointer] = 1
                pointer = (pointer + 1) % frame_count
            faults += 1
    
    return faults

内存保护与共享

内存保护机制

// 页表项中的保护位示例
typedef struct {
    unsigned int frame : 20;
    unsigned int valid : 1;
    unsigned int read : 1;    // 读权限
    unsigned int write : 1;   // 写权限
    unsigned int execute : 1; // 执行权限
    unsigned int user : 1;    // 用户/内核模式
} ProtectionEntry;

// 检查访问权限
int check_permission(unsigned int virtual_addr, int is_write, int is_user) {
    PageTableEntry *pte = get_page_table_entry(virtual_addr);
    
    if (!pte->valid) return 0;
    if (is_user && !pte->user) return 0;  // 用户不能访问内核空间
    if (is_write && !pte->write) return 0; // 写保护
    if (!pte->read) return 0;  // 无读权限
    
    return 1;
}

内存共享

// 共享内存实现
struct SharedMemory {
    int shmid;
    void *addr;
    int ref_count;
    char key[256];
};

// 映射共享内存到进程地址空间
void* map_shared_memory(const char *key, size_t size) {
    // 1. 创建或获取共享内存段
    int shmid = shmget(ftok(key, 1), size, IPC_CREAT | 0666);
    
    // 2. 附加到进程地址空间
    void *addr = shmat(shmid, NULL, 0);
    
    // 3. 更新引用计数
    update_ref_count(key, 1);
    
    return addr;
}

文件系统

文件系统是操作系统用于组织、存储和管理数据的机制。

文件的基本概念

文件的定义

  • 具有符号名的一组相关元素的有序序列
  • 文件系统中的基本存储单位
  • 包含数据、元数据和属性

文件属性

  • 文件名
  • 文件类型(普通文件、目录文件、设备文件等)
  • 文件大小
  • 创建/修改/访问时间
  • 权限(读、写、执行)
  • 所有者信息

文件结构

1. 无结构文件(流式文件)

  • 数据是一串字节流
  • 例如:Unix/Linux中的文件
  • 优点:灵活,用户自行解释结构

2. 记录式文件(结构文件)

  • 由固定或可变长度的记录组成
  • 例如:数据库文件
  • 记录是存取的基本单位

文件目录结构

1. 单级目录

  • 所有文件在同一目录下
  • 简单但不允许重名

2. 两级目录

  • 每个用户有自己的目录
  • 解决了重名问题

3. 树形目录

  • 层次化结构,支持嵌套
  • 路径名:/usr/local/bin/ls
  • 当前目录:工作目录

4. 无环图目录

  • 支持链接(硬链接、软链接)
  • 允许共享

文件系统层次结构

用户接口层
    ↓
文件系统接口层
    ↓
基本文件系统层(缓冲区管理)
    ↓
设备组织层(I/O调度)
    ↓
设备接口层

文件存储空间管理

1. 空闲表法

// 空闲表结构
struct FreeBlock {
    int start_block;
    int length;
    struct FreeBlock *next;
};

// 分配连续空间
int allocate_contiguous(struct FreeBlock **free_list, int size) {
    struct FreeBlock *current = *free_list;
    struct FreeBlock *prev = NULL;
    
    while (current) {
        if (current->length >= size) {
            int allocated_start = current->start_block;
            current->start_block += size;
            current->length -= size;
            
            if (current->length == 0) {
                if (prev) prev->next = current->next;
                else *free_list = current->next;
                free(current);
            }
            return allocated_start;
        }
        prev = current;
        current = current->next;
    }
    return -1;  // 空间不足
}

2. 位图法

// 位图表示例
#define BITMAP_SIZE 1024
unsigned char bitmap[BITMAP_SIZE];  // 每位表示一个块

// 查找连续的空闲块
int find_free_blocks(int count) {
    for (int i = 0; i < BITMAP_SIZE; i++) {
        if (bitmap[i] != 0xFF) {  // 有空闲位
            for (int bit = 0; bit < 8; bit++) {
                if (!(bitmap[i] & (1 << bit))) {
                    // 检查后续块
                    int start = i * 8 + bit;
                    int free_count = 0;
                    for (int j = 0; j < count && start + j < BITMAP_SIZE * 8; j++) {
                        int byte = (start + j) / 8;
                        int b = (start + j) % 8;
                        if (!(bitmap[byte] & (1 << b))) free_count++;
                        else break;
                    }
                    if (free_count >= count) return start;
                }
            }
        }
    }
    return -1;
}

// 分配块
void allocate_blocks(int start, int count) {
    for (int i = 0; i < count; i++) {
        int byte = (start + i) / 8;
        int bit = (start + i) % 8;
        bitmap[byte] |= (1 << bit);
    }
}

3. 成组链接法(Unix)

// 超级块结构
struct SuperBlock {
    int s_nfree;          // 空闲块数量
    int s_free[100];      // 空闲块索引表
    // 其他元数据...
};

// 分配空闲块
int allocate_block(struct SuperBlock *sb, int device) {
    if (sb->s_nfree <= 0) return -1;
    
    int block = sb->s_free[--sb->s_nfree];
    
    if (sb->s_nfree == 0) {
        // 读取下一个索引块
        read_block(device, sb->s_free[0], (char*)sb->s_free);
        sb->s_nfree = sb->s_free[0];
    }
    
    return block;
}

文件分配方法

1. 连续分配

// 目录项结构
struct DirectoryEntry {
    char name[256];
    int start_block;
    int length;
    // 其他属性...
};

// 读取文件
void read_file_contiguous(struct DirectoryEntry *entry, char *buffer) {
    read_blocks(entry->start_block, entry->length, buffer);
}

2. 链接分配

// 索引块结构
struct IndexBlock {
    int pointers[128];  // 指向数据块
};

// 读取文件
void read_file_linked(int start_block, char *buffer) {
    int current = start_block;
    int offset = 0;
    
    while (current != -1) {
        read_block(current, buffer + offset);
        offset += BLOCK_SIZE;
        
        // 读取下一个块号
        int next;
        read_block(current, (char*)&next);
        current = next;
    }
}

3. 索引分配

// Unix inode结构
struct inode {
    int i_mode;         // 文件类型和权限
    int i_nlink;        // 硬链接数
    int i_size;         // 文件大小
    int i_blocks;       // 占用块数
    int i_block[15];    // 直接/间接索引块
    // 其他元数据...
};

// 读取文件数据块
int get_data_block(struct inode *inode, int logical_block) {
    if (logical_block < 12) {
        // 直接索引
        return inode->i_block[logical_block];
    } else if (logical_block < 12 + 128) {
        // 一级间接索引
        int indirect_block = inode->i_block[12];
        int index = logical_block - 12;
        int block;
        read_block(indirect_block, (char*)&block + index * sizeof(int));
        return block;
    } else if (logical_block < 12 + 128 + 128 * 128) {
        // 二级间接索引
        int indirect_block = inode->i_block[13];
        int index1 = (logical_block - 12 - 128) / 128;
        int index2 = (logical_block - 12 - 128) % 128;
        
        int block1;
        read_block(indirect_block, (char*)&block1 + index1 * sizeof(int));
        
        int block2;
        read_block(block1, (char*)&block2 + index2 * sizeof(int));
        return block2;
    }
    return -1;
}

文件系统实现

1. 文件系统层次结构

// 文件系统结构
struct FileSystem {
    struct SuperBlock *superblock;
    struct inode *inode_table;
    struct FileDescriptor *fd_table;
    // 其他组件...
};

// 打开文件
int open(const char *pathname, int flags) {
    // 1. 路径解析
    struct inode *dir_inode = resolve_path(pathname);
    
    // 2. 查找文件
    struct inode *file_inode = find_entry(dir_inode, basename(pathname));
    
    if (!file_inode && (flags & O_CREAT)) {
        // 创建文件
        file_inode = create_file(dir_inode, basename(pathname));
    }
    
    if (!file_inode) return -1;
    
    // 3. 检查权限
    if (!check_permission(file_inode, flags)) return -1;
    
    // 4. 分配文件描述符
    int fd = allocate_fd();
    file_table[fd].inode = file_inode;
    file_table[fd].flags = flags;
    file_table[fd].offset = 0;
    
    return fd;
}

2. 缓冲区管理

// 缓冲区头
struct Buffer {
    int block_number;
    int device;
    int dirty;      // 是否被修改
    int valid;      // 数据是否有效
    char data[512];
    struct Buffer *next;
    struct Buffer *prev;
};

// 缓冲区队列
struct Buffer *cache_head = NULL;
struct Buffer *cache_tail = NULL;

// 缓冲区查找
struct Buffer* get_block(int device, int block) {
    // 查找缓存
    struct Buffer *bp = cache_head;
    while (bp) {
        if (bp->device == device && bp->block_number == block) {
            // 移到链表头部(LRU)
            remove_from_list(bp);
            add_to_head(bp);
            return bp;
        }
        bp = bp->next;
    }
    
    // 缓存未命中,从磁盘读取
    bp = allocate_buffer();
    read_from_disk(device, block, bp->data);
    bp->device = device;
    bp->block_number = block;
    bp->valid = 1;
    
    // 添加到缓存
    add_to_head(bp);
    return bp;
}

文件系统操作

1. 文件读写

// 读取文件
ssize_t read(int fd, void *buf, size_t count) {
    struct FileDescriptor *fildes = &file_table[fd];
    struct inode *inode = fildes->inode;
    
    if (!(fildes->flags & O_RDONLY)) return -1;
    
    size_t bytes_read = 0;
    size_t remaining = count;
    
    while (remaining > 0 && fildes->offset < inode->i_size) {
        // 计算逻辑块号和块内偏移
        int logical_block = fildes->offset / BLOCK_SIZE;
        int block_offset = fildes->offset % BLOCK_SIZE;
        
        // 获取物理块号
        int physical_block = get_data_block(inode, logical_block);
        if (physical_block == -1) break;
        
        // 读取块
        struct Buffer *bp = get_block(inode->i_dev, physical_block);
        
        // 复制数据
        int to_copy = min(BLOCK_SIZE - block_offset, remaining);
        to_copy = min(to_copy, inode->i_size - fildes->offset);
        
        memcpy(buf + bytes_read, bp->data + block_offset, to_copy);
        
        bytes_read += to_copy;
        remaining -= to_copy;
        fildes->offset += to_copy;
    }
    
    return bytes_read;
}

// 写入文件
ssize_t write(int fd, const void *buf, size_t count) {
    struct FileDescriptor *fildes = &file_table[fd];
    struct inode *inode = fildes->inode;
    
    if (!(fildes->flags & O_WRONLY)) return -1;
    
    size_t bytes_written = 0;
    size_t remaining = count;
    
    while (remaining > 0) {
        int logical_block = fildes->offset / BLOCK_SIZE;
        int block_offset = fildes->offset % BLOCK_SIZE;
        
        // 获取或分配物理块
        int physical_block = get_data_block(inode, logical_block);
        if (physical_block == -1) {
            physical_block = allocate_block(inode);
            if (physical_block == -1) break;
        }
        
        struct Buffer *bp = get_block(inode->i_dev, physical_block);
        
        int to_copy = min(BLOCK_SIZE - block_offset, remaining);
        memcpy(bp->data + block_offset, buf + bytes_written, to_copy);
        bp->dirty = 1;
        
        bytes_written += to_copy;
        remaining -= to_copy;
        fildes->offset += to_copy;
        
        if (fildes->offset > inode->i_size) {
            inode->i_size = fildes->offset;
            inode->i_dirty = 1;
        }
    }
    
    return bytes_written;
}

2. 目录操作

// 目录项结构
struct dir_entry {
    int inode;
    char name[256];
};

// 创建目录
int mkdir(const char *pathname, mode_t mode) {
    // 1. 解析父目录
    char parent_path[PATH_MAX];
    char dir_name[NAME_MAX];
    split_path(pathname, parent_path, dir_name);
    
    struct inode *parent = resolve_path(parent_path);
    if (!parent) return -1;
    
    // 2. 检查是否已存在
    if (find_entry(parent, dir_name)) return -1;
    
    // 3. 分配新inode
    struct inode *new_inode = allocate_inode();
    new_inode->i_mode = S_IFDIR | mode;
    new_inode->i_nlink = 1;
    
    // 4. 创建"."和".."条目
    struct dir_entry dot = {new_inode->i_ino, "."};
    struct dir_entry dotdot = {parent->i_ino, ".."};
    
    write(new_inode, &dot, sizeof(dot));
    write(new_inode, &dotdot, sizeof(dotdot));
    
    // 5. 添加到父目录
    struct dir_entry entry = {new_inode->i_ino, dir_name};
    write(parent, &entry, sizeof(entry));
    
    parent->i_nlink++;  // 增加父目录链接计数
    
    return 0;
}

3. 链接操作

// 创建硬链接
int link(const char *oldpath, const char *newpath) {
    struct inode *old_inode = resolve_path(oldpath);
    if (!old_inode) return -1;
    
    // 不能链接目录(防止循环)
    if (S_ISDIR(old_inode->i_mode)) return -1;
    
    char parent_path[PATH_MAX];
    char new_name[NAME_MAX];
    split_path(newpath, parent_path, new_name);
    
    struct inode *parent = resolve_path(parent_path);
    if (!parent) return -1;
    
    // 添加目录项
    struct dir_entry entry = {old_inode->i_ino, new_name};
    write(parent, &entry, sizeof(entry));
    
    // 增加链接计数
    old_inode->i_nlink++;
    
    return 0;
}

// 创建符号链接
int symlink(const char *target, const char *linkpath) {
    // 创建一个特殊文件,内容是目标路径
    int fd = creat(linkpath, 0777);
    if (fd < 0) return -1;
    
    write(fd, target, strlen(target));
    close(fd);
    
    // 设置特殊类型
    struct inode *inode = resolve_path(linkpath);
    inode->i_mode = S_IFLNK | 0777;
    
    return 0;
}

文件系统挂载

// 挂载表结构
struct Mount {
    char device[256];
    char mount_point[256];
    struct FileSystem *fs;
    struct Mount *next;
};

struct Mount *mount_table = NULL;

// 挂载文件系统
int mount(const char *device, const char *mount_point, const char *fs_type) {
    // 1. 查找挂载点
    struct inode *mp_inode = resolve_path(mount_point);
    if (!mp_inode || !S_ISDIR(mp_inode->i_mode)) return -1;
    
    // 2. 读取设备超级块
    struct SuperBlock *sb = read_superblock(device);
    if (!sb) return -1;
    
    // 3. 创建挂载项
    struct Mount *mnt = malloc(sizeof(struct Mount));
    strcpy(mnt->device, device);
    strcpy(mnt->mount_point, mount_point);
    mnt->fs = init_filesystem(sb, device);
    
    // 4. 添加到挂载表
    mnt->next = mount_table;
    mount_table = mnt;
    
    return 0;
}

// 路径解析
struct inode* resolve_path(const char *pathname) {
    if (pathname[0] == '/') {
        // 绝对路径,从根目录开始
        current = root_inode;
    } else {
        // 相对路径,从当前目录开始
        current = current_inode;
    }
    
    char path[PATH_MAX];
    strcpy(path, pathname);
    char *token = strtok(path, "/");
    
    while (token) {
        // 检查是否挂载点
        struct Mount *mnt = find_mount(token);
        if (mnt) {
            current = mnt->fs->root_inode;
        } else {
            current = find_entry(current, token);
        }
        
        if (!current) return NULL;
        token = strtok(NULL, "/");
    }
    
    return current;
}

设备管理

设备管理负责管理计算机的外部设备,包括输入输出设备、存储设备等。

设备分类

1. 按传输速率分类

  • 低速设备:键盘、鼠标(几B/s ~ 几KB/s)
  • 中速设备:打印机、扫描仪(几KB/s ~ 几百KB/s)
  • 高速设备:磁盘、光盘、网卡(几MB/s ~ 几GB/s)

2. 按信息组织分类

  • 字符设备:以字符为单位(如终端、打印机)
  • 块设备:以数据块为单位(如磁盘、光盘)

3. 按共享特性分类

  • 独占设备:只能由一个进程使用(如打印机)
  • 共享设备:可由多个进程同时使用(如磁盘)
  • 虚拟设备:通过SPOOLing技术实现共享

I/O系统层次结构

用户进程
    ↓
设备无关OS软件
    ↓
设备驱动程序
    ↓
中断处理程序
    ↓
硬件

I/O控制方式

1. 程序I/O(轮询)

// 轮询方式读取键盘输入
char poll_keyboard() {
    while (!keyboard_ready()) {
        // 忙等待
        ; 
    }
    return keyboard_data();
}

2. 中断驱动I/O

// 中断处理程序
void keyboard_isr() {
    char ch = inb(KEYBOARD_DATA_PORT);
    // 保存到缓冲区
    kb_buffer[kb_head++] = ch;
    kb_head %= KB_BUFFER_SIZE;
}

// 读取函数
char read_keyboard() {
    while (kb_head == kb_tail) {
        // 等待中断
        sleep();
    }
    char ch = kb_buffer[kb_tail++];
    kb_tail %= KB_BUFFER_SIZE;
    return ch;
}

3. DMA方式

// DMA控制器结构
struct DMAController {
    unsigned int channel;
    unsigned int address;
    unsigned int count;
    unsigned int mode;
};

// 设置DMA传输
void setup_dma(void *buffer, int size, int direction) {
    struct DMAController *dma = DMA_BASE;
    
    outb(dma->channel | 0x04, DMA_CMD);  // 禁用通道
    outb(dma->channel | 0x00, DMA_MODE); // 设置模式
    
    // 传输地址
    outb((unsigned int)buffer & 0xFF, DMA_ADDR(dma->channel));
    outb(((unsigned int)buffer >> 8) & 0xFF, DMA_ADDR(dma->channel));
    outb(((unsigned int)buffer >> 16) & 0xFF, DMA_ADDR(dma->channel));
    
    // 传输计数
    outb((size - 1) & 0xFF, DMA_COUNT(dma->channel));
    outb(((size - 1) >> 8) & 0xFF, DMA_COUNT(dma->channel));
    
    outb(dma->channel, DMA_CMD);  // 启用通道
}

I/O子系统

1. I/O调度

// I/O请求队列
struct IORequest {
    int device;
    int block;
    void *buffer;
    int direction;  // 0=读, 1=写
    int priority;
    struct IORequest *next;
};

// 电梯算法(SCAN)
void schedule_io(struct IORequest **queue) {
    if (!*queue) return;
    
    // 按设备和块号排序
    struct IORequest *current = *queue;
    struct IORequest *sorted = NULL;
    
    while (current) {
        struct IORequest *next = current->next;
        
        // 插入排序
        if (!sorted || current->block < sorted->block) {
            current->next = sorted;
            sorted = current;
        } else {
            struct IORequest *temp = sorted;
            while (temp->next && temp->next->block < current->block) {
                temp = temp->next;
            }
            current->next = temp->next;
            temp->next = current;
        }
        
        current = next;
    }
    
    *queue = sorted;
}

2. 缓冲区管理

// 双缓冲区
struct DoubleBuffer {
    char buffer1[BLOCK_SIZE];
    char buffer2[BLOCK_SIZE];
    int active;  // 当前活动缓冲区
    int ready;   // 就绪缓冲区
};

// 双缓冲读取
void read_with_double_buffer(struct DoubleBuffer *db, int device, int block) {
    // 启动DMA到buffer1
    setup_dma(db->buffer1, BLOCK_SIZE, READ);
    start_device(device);
    
    while (1) {
        // 等待buffer1填满
        wait_for_completion();
        
        // 同时启动DMA到buffer2
        setup_dma(db->buffer2, BLOCK_SIZE, READ);
        start_device(device);
        
        // 处理buffer1
        process_data(db->buffer1);
        
        // 等待buffer2填满
        wait_for_completion();
        
        // 同时启动DMA到buffer1
        setup_dma(db->buffer1, BLOCK_SIZE, READ);
        start_device(device);
        
        // 处理buffer2
        process_data(db->buffer2);
    }
}

设备驱动程序

1. 设备驱动框架

// 设备驱动结构
struct DeviceDriver {
    char name[32];
    int (*init)(void);
    int (*open)(int minor);
    int (*read)(int minor, void *buf, int count);
    int (*write)(int minor, const void *buf, int count);
    int (*ioctl)(int minor, int cmd, void *arg);
    int (*close)(int minor);
};

// 字符设备驱动示例:虚拟终端
struct tty_driver {
    struct DeviceDriver base;
    // 特定数据...
};

int tty_read(int minor, void *buf, int count) {
    struct tty_struct *tty = &tty_table[minor];
    
    // 从输入队列读取
    while (tty->read_buf_count == 0) {
        sleep_on(&tty->read_wait);
    }
    
    int n = min(count, tty->read_buf_count);
    memcpy(buf, tty->read_buf, n);
    
    // 移动剩余数据
    memmove(tty->read_buf, tty->read_buf + n, tty->read_buf_count - n);
    tty->read_buf_count -= n;
    
    return n;
}

int tty_write(int minor, const void *buf, int count) {
    struct tty_struct *tty = &tty_table[minor];
    const char *p = buf;
    
    for (int i = 0; i < count; i++) {
        // 输出到硬件
        outb(tty->io_base, *p++);
        
        // 处理特殊字符
        if (*p == '\n') outb(tty->io_base, '\r');
    }
    
    return count;
}

2. 块设备驱动

// 磁盘驱动示例
struct disk_device {
    int io_base;
    int irq;
    int cylinders;
    int heads;
    int sectors;
};

// 磁盘读取
int disk_read(struct disk_device *disk, int sector, void *buffer, int count) {
    // 等待磁盘就绪
    while (inb(disk->io_base + 7) & 0x80);
    
    // 选择驱动器和磁头
    outb(disk->io_base + 6, 0xA0 | (disk->heads > 8 ? 0x10 : 0) | ((sector / disk->sectors) & 0x0F));
    
    // 设置扇区数
    outb(disk->io_base + 2, count);
    
    // 设置LBA地址
    outb(disk->io_base + 3, sector & 0xFF);
    outb(disk->io_base + 4, (sector >> 8) & 0xFF);
    outb(disk->io_base + 5, (sector >> 16) & 0xFF);
    
    // 发送读命令
    outb(disk->io_base + 7, 0x20);
    
    // 读取数据
    for (int i = 0; i < count * 256; i++) {
        // 等待数据就绪
        while (!(inb(disk->io_base + 7) & 0x08));
        
        // 读取16位数据
        unsigned short data = inw(disk->io_base);
        ((unsigned short*)buffer)[i] = data;
    }
    
    return count;
}

SPOOLing技术

假脱机系统

// SPOOLing目录结构
struct SPOOL {
    char device[32];
    int active;  // 是否激活
    // 输入井和输出井
    char input井[井大小];
    char output井[井大小];
};

// 打印机SPOOLing
void spool_print(const char *data, int len) {
    // 1. 将数据写入输出井
    char filename[256];
    sprintf(filename, "/spool/printer/%d", get_unique_id());
    
    int fd = open(filename, O_CREAT | O_WRONLY);
    write(fd, data, len);
    close(fd);
    
    // 2. 如果打印机空闲,启动打印进程
    if (!printer_busy) {
        pid_t pid = fork();
        if (pid == 0) {
            // 打印守护进程
            print_daemon();
            exit(0);
        }
    }
}

void print_daemon() {
    while (1) {
        // 扫描输出井
        char *file = find_next_spool_file("/spool/printer");
        if (!file) break;
        
        // 读取并打印
        int fd = open(file, O_RDONLY);
        char buffer[4096];
        int n;
        while ((n = read(fd, buffer, sizeof(buffer))) > 0) {
            // 发送到打印机
            write_to_printer(buffer, n);
        }
        close(fd);
        
        // 删除已完成的作业
        unlink(file);
    }
}

设备无关性

1. 设备文件

// 设备文件结构
struct dev_t {
    unsigned int major;  // 主设备号(驱动类型)
    unsigned int minor;  // 次设备号(具体设备)
};

// 设备文件操作
int device_open(const char *path, int flags) {
    struct stat st;
    if (stat(path, &st) < 0) return -1;
    
    if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
        return -1;  // 不是设备文件
    }
    
    dev_t dev = st.st_rdev;
    struct DeviceDriver *driver = get_driver(major(dev));
    
    if (!driver) return -1;
    
    return driver->open(minor(dev));
}

2. 缓冲区缓存

// 块设备缓存
struct buffer_cache {
    int device;
    int block;
    int valid;
    int dirty;
    char data[BLOCK_SIZE];
    struct buffer_cache *next;
    struct buffer_cache *prev;
};

// 缓存查找
struct buffer_cache* get_buffer(int device, int block) {
    // 查找缓存
    struct buffer_cache *bp = find_in_cache(device, block);
    if (bp) return bp;
    
    // 缓存未命中
    bp = allocate_buffer();
    read_from_device(device, block, bp->data);
    bp->device = device;
    bp->block = block;
    bp->valid = 1;
    
    // 添加到缓存
    add_to_cache(bp);
    return bp;
}

电源管理

1. ACPI(高级配置和电源接口)

// 电源状态
typedef enum {
    POWER_WORKING,
    POWER_SLEEP,
    POWER_HIBERNATE,
    POWER_OFF
} PowerState;

// 电源管理函数
void enter_sleep_state() {
    // 1. 保存所有进程状态
    save_all_processes();
    
    // 2. 将内存内容写入磁盘(Hibernate)
    write_memory_to_disk();
    
    // 3. 发送ACPI命令
    outb(ACPI_PM1a_CNT, SLEEP_ENABLE);
    
    // 4. 进入睡眠状态
    asm("hlt");
}

// 设备电源管理
void set_device_power(struct device *dev, int power_state) {
    if (power_state == POWER_OFF) {
        // 关闭设备
        dev->driver->shutdown(dev);
        // 关闭时钟
        disable_clock(dev);
    } else if (power_state == POWER_WORKING) {
        // 启用设备
        enable_clock(dev);
        dev->driver->init(dev);
    }
}

系统安全与发展趋势

系统安全基础

安全目标(CIA三元组)

  • 机密性(Confidentiality):防止未授权访问
  • 完整性(Integrity):防止未授权修改
  • 可用性(Availability):确保授权用户可访问

访问控制

1. 自主访问控制(DAC)

// Unix权限模型
struct file_permissions {
    unsigned int owner_read : 1;
    unsigned int owner_write : 1;
    unsigned int owner_execute : 1;
    unsigned int group_read : 1;
    unsigned int group_write : 1;
    unsigned int group_execute : 1;
    unsigned int other_read : 1;
    unsigned int other_write : 1;
    unsigned int other_execute : 1;
};

// 权限检查
int check_permission(struct inode *inode, int mode, struct user *user) {
    if (user->uid == 0) return 1;  // root有所有权限
    
    if (user->uid == inode->i_uid) {
        // 所有者
        if (mode == READ && !inode->perm.owner_read) return 0;
        if (mode == WRITE && !inode->perm.owner_write) return 0;
        if (mode == EXECUTE && !inode->perm.owner_execute) return 0;
    } else if (user->gid == inode->i_gid) {
        // 组
        if (mode == READ && !inode->perm.group_read) return 0;
        if (mode == WRITE && !inode->perm.group_write) return 0;
        if (mode == EXECUTE && !inode->perm.group_execute) return 0;
    } else {
        // 其他
        if (mode == READ && !inode->perm.other_read) return 0;
        if (mode == WRITE && !inode->perm.other_write) return 0;
        if (mode == EXECUTE && !inode->perm.other_execute) return 0;
    }
    
    return 1;
}

2. 强制访问控制(MAC)

// SELinux安全上下文
struct security_context {
    char user[32];
    char role[32];
    char type[32];  // 类型
    int level;      // 敏感级别
};

// MAC策略检查
int mac_check(struct security_context *subject, 
              struct security_context *object, 
              int operation) {
    // 读取策略规则
    // 规则格式:允许 subject.type 操作 object.type
    
    if (strcmp(subject->type, "trusted") == 0) {
        return 1;  // trusted类型有所有权限
    }
    
    if (strcmp(subject->type, "user") == 0 && 
        strcmp(object->type, "user_data") == 0 &&
        operation == READ) {
        return 1;  // 允许读取用户数据
    }
    
    return 0;  // 默认拒绝
}

身份认证

1. 密码认证

// 密码哈希存储
struct passwd_entry {
    char username[32];
    char password_hash[64];  // 存储哈希值
    int uid;
    int gid;
};

// 验证密码
int verify_password(const char *username, const char *password) {
    struct passwd_entry entry;
    
    // 从/etc/shadow读取
    if (get_user_entry(username, &entry) < 0) return 0;
    
    // 计算输入密码的哈希
    char *hash = crypt(password, entry.password_hash);
    
    return strcmp(hash, entry.password_hash) == 0;
}

// 密码哈希示例(使用SHA-256)
void hash_password(const char *password, char *output) {
    // 实际使用中应使用加盐哈希
    // 这里简化演示
    SHA256_CTX ctx;
    sha256_init(&ctx);
    sha256_update(&ctx, password, strlen(password));
    sha256_final(&ctx, output);
}

2. 多因素认证

// TOTP(基于时间的一次性密码)
int verify_totp(const char *secret, int user_code) {
    // 获取当前时间戳(30秒时间窗)
    uint64_t timestamp = time(NULL) / 30;
    
    // 生成预期代码
    int expected = generate_totp(secret, timestamp);
    
    // 允许前后一个时间窗(容错)
    int expected_prev = generate_totp(secret, timestamp - 1);
    int expected_next = generate_totp(secret, timestamp + 1);
    
    return (user_code == expected) || 
           (user_code == expected_prev) || 
           (user_code == expected_next);
}

内存保护

1. 地址空间布局随机化(ASLR)

// 进程创建时随机化内存布局
void setup_aslr(struct process *proc) {
    // 随机化栈起始地址
    proc->stack_start = STACK_BASE + (rand() % 0x10000000);
    
    // 随机化堆起始地址
    proc->heap_start = HEAP_BASE + (rand() % 0x10000000);
    
    // 随机化共享库加载地址
    proc->lib_start = LIB_BASE + (rand() % 0x10000000);
}

2. 数据执行保护(DEP/NX)

// 页表项中的NX位(不可执行位)
typedef struct {
    unsigned int frame : 20;
    unsigned int valid : 1;
    unsigned int nx : 1;  // No Execute
    // 其他标志...
} PageTableEntry_DEP;

// 设置内存页为不可执行
void set_no_execute(void *addr) {
    PageTableEntry_DEP *pte = get_page_table_entry(addr);
    pte->nx = 1;
    flush_tlb();
}

3. 栈保护

// 栈溢出保护(金丝雀值)
void vulnerable_function() {
    int canary = generate_canary();  // 随机值
    
    char buffer[64];
    
    // 函数结束时检查
    if (canary != expected_canary) {
        // 栈溢出检测
        abort();
    }
}

加密与安全通信

1. 文件加密

// 文件加密结构
struct encrypted_file {
    char iv[16];           // 初始化向量
    char key[32];          // 加密密钥(应从用户密码派生)
    char ciphertext[0];    // 加密数据
};

// 加密文件写入
void write_encrypted_file(const char *path, const void *data, int len, const char *password) {
    // 1. 从密码派生密钥
    char key[32];
    derive_key(password, key);
    
    // 2. 生成随机IV
    char iv[16];
    random_bytes(iv, 16);
    
    // 3. 加密数据
    char *encrypted = malloc(len + 16);
    AES_CBC_encrypt(data, len, key, iv, encrypted);
    
    // 4. 写入文件
    int fd = open(path, O_CREAT | O_WRONLY, 0600);
    write(fd, iv, 16);
    write(fd, encrypted, len + 16);
    close(fd);
    
    free(encrypted);
}

2. 安全通信(TLS简化版)

// 安全连接结构
struct secure_connection {
    int socket;
    char session_key[32];
    char iv[16];
    // 公钥/私钥...
};

// 建立安全连接
int establish_secure_connection(struct secure_connection *conn, int sockfd) {
    // 1. 生成临时密钥对
    generate_keypair(&conn->public_key, &conn->private_key);
    
    // 2. 交换公钥
    send(sockfd, &conn->public_key, sizeof(conn->public_key), 0);
    recv(sockfd, &conn->peer_public_key, sizeof(conn->peer_public_key), 0);
    
    // 3. 计算共享密钥(Diffie-Hellman)
    derive_shared_secret(&conn->private_key, &conn->peer_public_key, conn->session_key);
    
    // 4. 生成IV
    random_bytes(conn->iv, 16);
    
    conn->socket = sockfd;
    return 0;
}

// 安全发送
int secure_send(struct secure_connection *conn, const void *data, int len) {
    char *encrypted = malloc(len + 16);
    AES_CBC_encrypt(data, len, conn->session_key, conn->iv, encrypted);
    
    int result = send(conn->socket, encrypted, len + 16, 0);
    free(encrypted);
    return result;
}

系统审计与日志

1. 审计日志

// 审计事件结构
struct audit_event {
    time_t timestamp;
    int event_type;
    int uid;
    int pid;
    char summary[256];
    char details[1024];
};

// 记录事件
void audit_log(int event_type, const char *format, ...) {
    struct audit_event event;
    
    event.timestamp = time(NULL);
    event.event_type = event_type;
    event.uid = getuid();
    event.pid = getpid();
    
    va_list args;
    va_start(args, format);
    vsnprintf(event.details, sizeof(event.details), format, args);
    va_end(args);
    
    // 写入审计日志文件
    int fd = open("/var/log/audit.log", O_WRONLY | O_APPEND);
    write(fd, &event, sizeof(event));
    close(fd);
    
    // 如果是高危事件,发送警报
    if (event_type >= AUDIT_CRITICAL) {
        send_security_alert(&event);
    }
}

2. 入侵检测

// 简单的异常检测
void detect_anomalies() {
    // 检测暴力破解
    int failed_logins = count_failed_logins_last_minute();
    if (failed_logins > 5) {
        audit_log(AUDIT_ALERT, "可能的暴力破解攻击,失败登录次数:%d", failed_logins);
        block_ip(get_attacker_ip());
    }
    
    // 检测异常进程
    struct process *proc;
    for_each_process(proc) {
        if (proc->cpu_usage > 90 && proc->memory_usage > 500MB) {
            audit_log(AUDIT_WARNING, "异常进程:PID=%d, CPU=%.1f%%, MEM=%.1fMB",
                      proc->pid, proc->cpu_usage, proc->memory_usage);
        }
    }
}

现代操作系统发展趋势

1. 云操作系统

  • 特点

    • 资源池化与弹性伸缩
    • 多租户隔离
    • 微服务架构
    • 容器化部署
  • 关键技术

    • Docker容器技术
    • Kubernetes编排
    • Serverless计算

2. 分布式操作系统

// 分布式进程管理
struct distributed_process {
    char process_id[64];
    char node_id[32];
    int state;
    // 分布式锁
    struct distributed_lock *lock;
    // 一致性状态
    struct consistency_state *consistency;
};

// 分布式一致性协议(简化版Paxos)
int paxos_propose(int proposal_id, int value) {
    // 1. 准备阶段
    send_prepare(proposal_id);
    int promises = count_promises();
    if (promises < majority) return -1;
    
    // 2. 接受阶段
    send_accept(proposal_id, value);
    int accepts = count_accepts();
    if (accepts < majority) return -1;
    
    // 3. 学习阶段
    broadcast_learn(value);
    return 0;
}

3. 实时操作系统(RTOS)

// 实时任务调度
typedef struct {
    int task_id;
    void (*entry)(void);
    int priority;
    int period;        // 周期(毫秒)
    int deadline;      // 截止时间
    int wcet;          // 最坏执行时间
} RealTimeTask;

// 速率单调调度(RMS)
void rms_schedule(RealTimeTask *tasks, int n) {
    // 按周期排序(周期越短优先级越高)
    qsort(tasks, n, sizeof(RealTimeTask), compare_period);
    
    for (int i = 0; i < n; i++) {
        // 检查可调度性
        double utilization = 0;
        for (int j = 0; j <= i; j++) {
            utilization += (double)tasks[j].wcet / tasks[j].period;
        }
        
        double bound = i * (pow(2, 1.0/(i+1)) - 1);
        if (utilization > bound) {
            printf("任务%d不可调度\n", tasks[i].task_id);
            return;
        }
    }
    
    printf("所有任务可调度\n");
}

4. 嵌入式操作系统

  • 特点

    • 资源受限
    • 低功耗
    • 高可靠性
    • 实时性要求
  • 代表系统

    • FreeRTOS
    • Zephyr
    • VxWorks

5. 物联网操作系统

// IoT设备管理
struct iot_device {
    char device_id[32];
    char protocol[16];  // MQTT, CoAP, HTTP
    int power_level;
    int connectivity;
    void (*sensor_callback)(int value);
};

// 低功耗管理
void enter_low_power_mode(struct iot_device *dev) {
    // 1. 关闭非必要外设
    disable_peripherals();
    
    // 2. 降低CPU频率
    set_cpu_frequency(LOW_FREQ);
    
    // 3. 配置唤醒源
    enable_wakeup_timer(60);  // 60秒后唤醒
    enable_wakeup_interrupt(KEYPAD_PIN);
    
    // 4. 进入深度睡眠
    asm("WFI");  // Wait For Interrupt
}

6. 量子操作系统(前沿研究)

// 量子比特管理(概念性)
typedef struct {
    int qubit_id;
    double alpha;  // 量子态系数
    double beta;
    int entangled_with;  // 纠缠的量子比特
} QuantumBit;

// 量子任务调度
void schedule_quantum_task(struct quantum_program *prog) {
    // 量子纠错
    apply_error_correction(prog);
    
    // 量子门序列编译
    compile_quantum_gates(prog);
    
    // 执行并测量
    execute_and_measure(prog);
}

7. 生物启发操作系统

// 生物计算模型
struct neuron {
    double potential;
    double threshold;
    struct neuron **connections;
    int connection_count;
};

// 神经形态调度
void neural_schedule(struct process *proc) {
    // 模拟神经网络决策
    double priority = activate_neural_network(
        proc->cpu_usage,
        proc->memory_usage,
        proc->io_wait,
        proc->user_priority
    );
    
    proc->priority = (int)(priority * 100);
}

安全发展趋势

1. 零信任架构

// 零信任验证
int zero_trust_verify(struct request *req) {
    // 1. 持续验证
    if (!verify_identity(req->user)) return 0;
    
    // 2. 设备健康检查
    if (!check_device_health(req->device)) return 0;
    
    // 3. 上下文分析
    if (!analyze_context(req->location, req->time, req->behavior)) return 0;
    
    // 4. 最小权限
    if (!check_minimal_permission(req->action, req->resource)) return 0;
    
    // 5. 持续监控
    monitor_session(req->session);
    
    return 1;
}

2. 可信执行环境(TEE)

// TEE安全世界
void trusted_execution(struct trusted_app *app) {
    // 在安全世界执行
    enter_secure_world();
    
    // 访问安全存储
    char *secret = read_secure_storage();
    
    // 执行加密操作
    char *result = secure_hash(secret);
    
    // 返回结果
    exit_secure_world(result);
}

3. 后量子密码学

// 格基密码学(Lattice-based)
struct lattice_key {
    int dimension;
    int *matrix;
    int *vector;
};

// 后量子签名
int pq_sign(struct lattice_key *key, const char *message, char *signature) {
    // 基于格问题的签名方案
    // 如:Dilithium, Falcon
    return 0;
}

总结

操作系统作为计算机系统的核心软件,其核心内容涵盖了从基础概念到高级特性的完整体系。通过深入理解进程管理、内存管理、文件系统、设备管理以及安全机制,我们能够构建高效、安全、可靠的计算环境。

现代操作系统正朝着更加智能化、分布式、安全化的方向发展,云计算、物联网、量子计算等新技术的出现,为操作系统设计带来了新的挑战和机遇。掌握这些核心概念和实现技术,对于理解计算机系统的工作原理和开发高质量软件具有重要意义。

在未来的发展中,操作系统将更加注重:

  • 安全性:零信任、硬件级安全
  • 可扩展性:支持异构计算、分布式架构
  • 智能化:AI辅助的资源管理
  • 绿色计算:能源效率优化
  • 用户体验:无缝的多设备协同

这些趋势将推动操作系统技术持续演进,为数字世界提供更强大的基础支撑。