vault backup: 2026-06-13 23:46:22

This commit is contained in:
2026-06-13 23:46:22 +08:00
parent 9a3d58dd3b
commit 224c3dc574
33 changed files with 14997 additions and 0 deletions

View File

@@ -0,0 +1,360 @@
# 附录A Wrapper 库参考
## 概述
Wrapper 库是课程提供的 C 语言工具库,封装了课程用到的所有系统调用。每个 Wrapper 函数在内部调用对应的系统调用并检查返回值,出错时自动打印错误信息并终止程序,从而简化实验代码的编写。
源文件组成:
| 文件 | 说明 |
|------|------|
| `wrapper.h` | 头文件,包含所有函数声明、类型定义和常量 |
| `wrapper.c` | Wrapper 函数实现 |
| `ptwrapper.c` | POSIX 线程相关 Wrapper 函数 |
| `libwrapper.a` | 预编译的静态库 |
## 编译与使用
```bash
# 方法一:链接静态库
gcc -o program program.c -L. -lwrapper
# 方法二:链接静态库 + 线程支持
gcc -o program program.c -L. -lwrapper -lpthread
# 方法三:自行编译
gcc -c wrapper.c ptwrapper.c
ar rc libwrapper.a wrapper.o ptwrapper.o
gcc -o program program.c -L. -lwrapper -lpthread
```
## 头文件包含的系统头文件
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <setjmp.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <errno.h>
#include <math.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
```
## 常量与类型定义
```c
typedef struct sockaddr SA; // 简化 socket 地址类型转换
#define MAXLINE 8192 // 最大文本行长度
#define MAXBUF 8192 // 最大 I/O 缓冲区大小
#define LISTENQ 1024 // listen() 第二参数(连接队列长度)
#define DEF_MODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH
#define DEF_UMASK S_IWGRP|S_IWOTH
// Robust I/O 缓冲区
typedef struct {
int rio_fd;
int rio_cnt;
char *rio_bufptr;
char rio_buf[8192];
} rio_t;
// System V 信号量联合体
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
```
---
## 进程控制
| 函数原型 | 对应系统调用 | 说明 |
|----------|-------------|------|
| `pid_t Fork(void)` | `fork` | 创建子进程 |
| `void Execve(const char *f, char *const a[], char *const e[])` | `execve` | 执行程序 |
| `pid_t Wait(int *status)` | `wait` | 等待任意子进程 |
| `pid_t Waitpid(pid_t pid, int *iptr, int options)` | `waitpid` | 等待指定子进程 |
| `void Kill(pid_t pid, int signum)` | `kill` | 发送信号 |
| `unsigned int Sleep(unsigned int secs)` | `sleep` | 休眠指定秒数 |
| `void Pause(void)` | `pause` | 暂停直到信号到达 |
| `unsigned int Alarm(unsigned int seconds)` | `alarm` | 设置定时器 |
| `void Setpgid(pid_t pid, pid_t pgid)` | `setpgid` | 设置进程组 |
| `pid_t Getpgrp(void)` | `getpgrp` | 获取当前进程组 |
**示例:**
```c
pid_t pid = Fork();
if (pid == 0) {
char *args[] = {"ls", "-la", NULL};
Execve("/bin/ls", args, environ);
} else {
int status;
Waitpid(pid, &status, 0);
printf("子进程退出状态: %d\n", WEXITSTATUS(status));
}
```
---
## 文件 I/O
| 函数原型 | 对应系统调用 | 说明 |
|----------|-------------|------|
| `int Open(const char *path, int flags, mode_t mode)` | `open` | 打开/创建文件 |
| `ssize_t Read(int fd, void *buf, size_t count)` | `read` | 读取数据 |
| `ssize_t Write(int fd, const void *buf, size_t count)` | `write` | 写入数据 |
| `off_t Lseek(int fd, off_t offset, int whence)` | `lseek` | 文件偏移定位 |
| `void Close(int fd)` | `close` | 关闭文件描述符 |
| `int Dup2(int fd1, int fd2)` | `dup2` | 复制文件描述符 |
| `int Select(int n, fd_set *r, fd_set *w, fd_set *e, struct timeval *t)` | `select` | I/O 多路复用 |
| `void Stat(const char *filename, struct stat *buf)` | `stat` | 获取文件状态 |
| `void Fstat(int fd, struct stat *buf)` | `fstat` | 获取文件状态 |
**示例:**
```c
int fd = Open("data.txt", O_RDONLY, 0);
char buf[MAXLINE];
ssize_t n = Read(fd, buf, MAXLINE);
Write(STDOUT_FILENO, buf, n);
Close(fd);
```
---
## 信号
| 函数原型 | 对应系统调用 | 说明 |
|----------|-------------|------|
| `handler_t *Signal(int signum, handler_t *handler)` | `signal` | 注册信号处理函数 |
| `void Sigprocmask(int how, const sigset_t *set, sigset_t *old)` | `sigprocmask` | 修改信号屏蔽字 |
| `void Sigemptyset(sigset_t *set)` | `sigemptyset` | 清空信号集 |
| `void Sigfillset(sigset_t *set)` | `sigfillset` | 填满信号集 |
| `void Sigaddset(sigset_t *set, int signum)` | `sigaddset` | 添加信号到集合 |
| `void Sigdelset(sigset_t *set, int signum)` | `sigdelset` | 从集合移除信号 |
| `int Sigismember(const sigset_t *set, int signum)` | `sigismember` | 判断信号是否在集合中 |
**示例:**
```c
void handler(int sig) {
printf("收到信号 %d\n", sig);
}
Signal(SIGINT, handler); // Ctrl+C 时调用 handler
```
---
## 标准 I/O
| 函数原型 | 对应标准库函数 | 说明 |
|----------|--------------|------|
| `FILE *Fopen(const char *name, const char *mode)` | `fopen` | 打开文件 |
| `void Fclose(FILE *fp)` | `fclose` | 关闭文件 |
| `char *Fgets(char *ptr, int n, FILE *stream)` | `fgets` | 读取一行 |
| `void Fputs(const char *ptr, FILE *stream)` | `fputs` | 写入一行 |
| `size_t Fread(void *ptr, size_t size, size_t nmemb, FILE *stream)` | `fread` | 二进制读取 |
| `void Fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)` | `fwrite` | 二进制写入 |
| `FILE *Fdopen(int fd, const char *type)` | `fdopen` | 文件描述符转 FILE* |
---
## 内存管理
| 函数原型 | 对应标准库函数 | 说明 |
|----------|--------------|------|
| `void *Malloc(size_t size)` | `malloc` | 分配内存 |
| `void *Realloc(void *ptr, size_t size)` | `realloc` | 重新分配内存 |
| `void *Calloc(size_t nmemb, size_t size)` | `calloc` | 分配并清零 |
| `void Free(void *ptr)` | `free` | 释放内存 |
---
## 内存映射
| 函数原型 | 对应系统调用 | 说明 |
|----------|-------------|------|
| `void *Mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)` | `mmap` | 创建内存映射 |
| `void Munmap(void *start, size_t length)` | `munmap` | 取消内存映射 |
---
## Socket 编程
| 函数原型 | 对应系统调用 | 说明 |
|----------|-------------|------|
| `int Socket(int domain, int type, int protocol)` | `socket` | 创建套接字 |
| `void Setsockopt(int s, int level, int opt, const void *val, int len)` | `setsockopt` | 设置套接字选项 |
| `void Bind(int sockfd, struct sockaddr *addr, int addrlen)` | `bind` | 绑定地址 |
| `void Listen(int s, int backlog)` | `listen` | 监听连接 |
| `int Accept(int s, struct sockaddr *addr, socklen_t *addrlen)` | `accept` | 接受连接 |
| `void Connect(int sockfd, struct sockaddr *addr, int addrlen)` | `connect` | 发起连接 |
---
## DNS 解析
| 函数原型 | 说明 |
|----------|------|
| `struct hostent *Gethostbyname(const char *name)` | 按主机名解析 |
| `struct hostent *Gethostbyaddr(const char *addr, int len, int type)` | 按地址解析 |
---
## 线程控制
| 函数原型 | 对应系统调用 | 说明 |
|----------|-------------|------|
| `void Pthread_create(pthread_t *tid, pthread_attr_t *attr, void *(*r)(void *), void *arg)` | `pthread_create` | 创建线程 |
| `void Pthread_join(pthread_t tid, void **retval)` | `pthread_join` | 等待线程结束 |
| `void Pthread_detach(pthread_t tid)` | `pthread_detach` | 分离线程 |
| `void Pthread_cancel(pthread_t tid)` | `pthread_cancel` | 取消线程 |
| `void Pthread_exit(void *retval)` | `pthread_exit` | 终止线程 |
| `pthread_t Pthread_self(void)` | `pthread_self` | 获取当前线程 ID |
| `void Pthread_once(pthread_once_t *once, void (*init)())` | `pthread_once` | 一次性初始化 |
---
## POSIX 信号量
| 函数原型 | 对应系统调用 | 说明 |
|----------|-------------|------|
| `void Sem_init(sem_t *sem, int pshared, unsigned int value)` | `sem_init` | 初始化信号量 |
| `void P(sem_t *sem)` | `sem_wait` | 等待P 操作,值减 1 |
| `void V(sem_t *sem)` | `sem_post` | 释放V 操作,值加 1 |
**示例(生产者-消费者):**
```c
sem_t mutex, slots, items;
Sem_init(&mutex, 0, 1);
Sem_init(&slots, 0, N);
Sem_init(&items, 0, 0);
// 生产者
P(&slots);
P(&mutex);
// 放入缓冲区
V(&mutex);
V(&items);
// 消费者
P(&items);
P(&mutex);
// 从缓冲区取出
V(&mutex);
V(&slots);
```
---
## Robust I/O (Rio)
| 函数原型 | 说明 |
|----------|------|
| `ssize_t rio_readn(int fd, void *buf, size_t n)` | 无缓冲读取 n 字节 |
| `ssize_t rio_writen(int fd, void *buf, size_t n)` | 无缓冲写入 n 字节 |
| `void rio_readinitb(rio_t *rp, int fd)` | 初始化缓冲读取 |
| `ssize_t rio_readnb(rio_t *rp, void *buf, size_t n)` | 带缓冲读取 n 字节 |
| `ssize_t rio_readlineb(rio_t *rp, void *buf, size_t maxlen)` | 带缓冲读取一行 |
**Wrapper 版本:** `Rio_readn``Rio_writen``Rio_readinitb``Rio_readnb``Rio_readlineb`
---
## 客户端/服务器辅助函数
| 函数原型 | 说明 |
|----------|------|
| `int open_client_sock(char *hostname, int port)` | 创建客户端套接字并连接 |
| `int open_listen_sock(int port)` | 创建服务器套接字并监听 |
| `int Open_client_sock(char *hostname, int port)` | 同上(带错误检查) |
| `int Open_listen_sock(int port)` | 同上(带错误检查) |
**示例(服务器):**
```c
int listen_fd = Open_listen_sock(8080);
struct sockaddr_in clientaddr;
socklen_t clientlen = sizeof(clientaddr);
int conn_fd = Accept(listen_fd, (SA *)&clientaddr, &clientlen);
```
**示例(客户端):**
```c
int sock_fd = Open_client_sock("localhost", 8080);
Send(sock_fd, "Hello", 5, 0);
```
---
## System V IPC
### 消息队列
| 函数原型 | 说明 |
|----------|------|
| `int Msgget(key_t key, int msgflg)` | 创建/获取消息队列 |
| `int Msgsnd(int msqid, const void *msg, size_t sz, int msgflg)` | 发送消息 |
| `int Msgrcv(int msqid, void *msg, size_t sz, long type, int msgflg)` | 接收消息 |
| `int Msgctl(int msqid, int cmd, struct msqid_ds *buf)` | 控制消息队列 |
### 共享内存
| 函数原型 | 说明 |
|----------|------|
| `int Shmget(key_t key, size_t size, int shmflg)` | 创建/获取共享内存 |
| `char *Shmat(int shmid, const void *addr, int shmflg)` | 附加共享内存 |
| `int Shmdt(const void *addr)` | 分离共享内存 |
| `int Shmctl(int shmid, int cmd, struct shmid_ds *buf)` | 控制共享内存 |
### System V 信号量
| 函数原型 | 说明 |
|----------|------|
| `int Semget(key_t key, int nsems, int semflg)` | 创建/获取信号量集 |
| `int Semctl(int semid, int semnum, int cmd, union semun arg)` | 控制信号量 |
| `int Semop(int semid, struct sembuf *sem, int sops)` | 操作信号量 |
### 命名管道
| 函数原型 | 说明 |
|----------|------|
| `int Mkfifo(const char *pathname, mode_t mode)` | 创建命名管道 (FIFO) |
---
## 错误处理函数
Wrapper 库内部使用以下错误处理函数,也可在自己的代码中直接调用:
| 函数 | 说明 |
|------|------|
| `void unix_error(char *msg)` | 打印系统调用错误并退出 |
| `void posix_error(int code, char *msg)` | 打印 POSIX 错误并退出 |
| `void dns_error(char *msg)` | 打印 DNS 错误并退出 |
| `void app_error(char *msg)` | 打印应用错误并退出 |

View File

@@ -0,0 +1,186 @@
# 附录B 操作系统术语表
> 本表收录课程涉及的核心术语,按中英文对照排列,涵盖进程管理、存储管理、文件系统、网络编程等领域。
---
## 进程与线程
| 英文术语 | 中文术语 | 简要说明 |
|----------|----------|----------|
| Process | 进程 | 程序的一次执行实例,是资源分配的基本单位 |
| Thread | 线程 | 进程内的执行单元,是 CPU 调度的基本单位 |
| Process Control Block (PCB) | 进程控制块 | 存储进程状态、寄存器、页表等信息的数据结构 |
| Process State | 进程状态 | 就绪、运行、阻塞等状态 |
| Ready | 就绪 | 等待 CPU 调度的状态 |
| Running | 运行 | 正在 CPU 上执行的状态 |
| Blocked / Waiting | 阻塞/等待 | 等待 I/O 或事件的状态 |
| Zombie Process | 僵尸进程 | 已终止但父进程未回收的进程 |
| Orphan Process | 孤儿进程 | 父进程已终止的进程,被 init 收养 |
| Daemon | 守护进程 | 在后台运行的长期服务进程 |
| Fork | 派生 | 创建子进程的系统调用 |
| Exec | 执行 | 用新程序替换当前进程映像 |
| Wait | 等待 | 父进程等待子进程终止 |
| Exit | 退出 | 进程终止并释放资源 |
| Process Group | 进程组 | 相关进程的集合 |
| Session | 会话 | 进程组的集合,关联一个控制终端 |
| Context Switch | 上下文切换 | CPU 从一个进程/线程切换到另一个 |
## 调度
| 英文术语 | 中文术语 | 简要说明 |
|----------|----------|----------|
| Scheduling | 调度 | 选择下一个运行的进程/线程 |
| Scheduler | 调度器 | 执行调度算法的模块 |
| CPU Burst | CPU 区间 | 进程使用 CPU 的时间段 |
| I/O Burst | I/O 区间 | 进程等待 I/O 的时间段 |
| Preemptive Scheduling | 抢占式调度 | 允许强制剥夺 CPU |
| Non-preemptive Scheduling | 非抢占式调度 | 进程主动释放 CPU |
| Round Robin (RR) | 时间片轮转 | 每个进程分配固定时间片 |
| Shortest Job First (SJF) | 最短作业优先 | 选择预计运行时间最短的进程 |
| Priority Scheduling | 优先级调度 | 按优先级选择进程 |
| Multilevel Feedback Queue | 多级反馈队列 | 多个就绪队列,动态调整优先级 |
| Starvation | 饥饿 | 进程长期得不到调度 |
| Fairness | 公平性 | 调度算法的公平程度 |
## 同步与互斥
| 英文术语 | 中文术语 | 简要说明 |
|----------|----------|----------|
| Synchronization | 同步 | 协调多个进程/线程的执行顺序 |
| Mutual Exclusion | 互斥 | 同一时刻只有一个进程进入临界区 |
| Critical Section | 临界区 | 访问共享资源的代码段 |
| Race Condition | 竞态条件 | 并发访问共享数据导致结果不确定 |
| Semaphore | 信号量 | 用于同步和互斥的计数器 |
| Mutex | 互斥锁 | 用于互斥的锁机制 |
| Lock | 锁 | 保护临界区的机制 |
| Deadlock | 死锁 | 多个进程互相等待,永远无法继续 |
| Starvation | 饥饿 | 进程长期无法获取资源 |
| Busy Waiting | 忙等待 | 循环检查条件,浪费 CPU |
| Condition Variable | 条件变量 | 线程间通知条件满足的机制 |
| Monitor | 管程 | 高级同步原语,封装共享数据和操作 |
| Producer-Consumer | 生产者-消费者 | 经典同步问题 |
| Readers-Writers | 读者-写者 | 经典同步问题 |
| Dining Philosophers | 哲学家就餐 | 经典同步问题 |
## 死锁
| 英文术语 | 中文术语 | 简要说明 |
|----------|----------|----------|
| Deadlock | 死锁 | 多个进程互相等待对方持有的资源 |
| Mutual Exclusion | 互斥条件 | 资源不能被共享 |
| Hold and Wait | 持有并等待 | 进程持有资源的同时等待新资源 |
| No Preemption | 不可剥夺 | 已分配的资源不能被强制收回 |
| Circular Wait | 循环等待 | 存在进程的循环等待链 |
| Deadlock Prevention | 死锁预防 | 破坏死锁的必要条件 |
| Deadlock Avoidance | 死锁避免 | 动态检查避免进入不安全状态 |
| Deadlock Detection | 死锁检测 | 检测死锁是否发生 |
| Safe State | 安全状态 | 存在安全序列的状态 |
| Banker's Algorithm | 银行家算法 | 经典的死锁避免算法 |
| Resource Allocation Graph | 资源分配图 | 描述资源分配关系的图 |
## 存储管理
| 英文术语 | 中文术语 | 简要说明 |
|----------|----------|----------|
| Memory Management | 存储管理 | 管理物理和虚拟内存 |
| Physical Address | 物理地址 | 内存硬件的实际地址 |
| Virtual Address | 虚拟地址 | 程序使用的逻辑地址 |
| Address Translation | 地址转换 | 虚拟地址到物理地址的映射 |
| Page | 页 | 虚拟地址空间的固定大小块 |
| Frame | 页框 | 物理内存的固定大小块 |
| Page Table | 页表 | 存储页到页框映射的表 |
| Translation Lookaside Buffer (TLB) | 转换后备缓冲器 | 页表的高速缓存 |
| Page Fault | 缺页 | 访问的页不在物理内存中 |
| Page Replacement | 页面替换 | 将页从磁盘调入内存,替换已有页 |
| Working Set | 工作集 | 进程当前使用的页面集合 |
| Thrashing | 抖动 | 频繁缺页导致性能急剧下降 |
| Segmentation | 分段 | 按逻辑单元划分地址空间 |
| Segmentation Fault | 段错误 | 访问非法内存地址 |
| Memory-Mapped File | 内存映射文件 | 将文件映射到进程地址空间 |
## 虚拟存储
| 英文术语 | 中文术语 | 简要说明 |
|----------|----------|----------|
| Virtual Memory | 虚拟存储 | 用磁盘扩展内存的技术 |
| Demand Paging | 请求分页 | 按需加载页面 |
| Copy-on-Write (COW) | 写时复制 | fork 时共享页面,写入时才复制 |
| Least Recently Used (LRU) | 最近最少使用 | 替换最久未使用的页面 |
| First-In-First-Out (FIFO) | 先进先出 | 替换最早进入的页面 |
| Clock Algorithm | 时钟算法 | LRU 的近似算法 |
| Dirty Page | 脏页 | 被修改过的页面 |
| Resident Set | 驻留集 | 进程在物理内存中的页面集合 |
| Swap | 交换 | 将整个进程在内存和磁盘间移动 |
| Swapping | 交换技术 | 在内存和外存间移动进程 |
## 文件系统
| 英文术语 | 中文术语 | 简要说明 |
|----------|----------|----------|
| File System | 文件系统 | 管理文件和目录的系统 |
| File Descriptor | 文件描述符 | 打开文件的整数标识符 |
| Inode | 索引节点 | 存储文件元信息的数据结构 |
| Directory | 目录 | 包含文件名和 inode 映射的特殊文件 |
| Hard Link | 硬链接 | 指向同一 inode 的多个目录项 |
| Symbolic Link (Symlink) | 符号链接 | 包含目标路径的特殊文件 |
| Mount | 挂载 | 将文件系统关联到目录树 |
| Block | 块 | 磁盘 I/O 的基本单位 |
| Superblock | 超级块 | 存储文件系统元信息的块 |
| File Allocation Table (FAT) | 文件分配表 | 一种文件系统组织方式 |
| Journaling | 日志 | 记录文件系统操作以保证一致性 |
| I-node Number | i-node 编号 | inode 的唯一标识 |
## I/O 系统
| 英文术语 | 中文术语 | 简要说明 |
|----------|----------|----------|
| System Call | 系统调用 | 用户程序请求内核服务的接口 |
| Trap | 陷入 | 从用户态切换到内核态 |
| Interrupt | 中断 | 硬件或软件发出的异步事件 |
| Device Driver | 设设备驱动 | 控制硬件设备的软件 |
| DMA (Direct Memory Access) | 直接内存访问 | 设备直接读写内存,无需 CPU |
| Buffer | 缓冲区 | 临时存储数据的区域 |
| Spooling | 假脱机 | 将设备输出先写到磁盘 |
| Blocking I/O | 阻塞 I/O | I/O 未完成时进程被阻塞 |
| Non-blocking I/O | 非阻塞 I/O | I/O 未完成时立即返回 |
| I/O Multiplexing | I/O 多路复用 | 用 select/poll/epoll 同时监听多个 I/O |
| Asynchronous I/O | 异步 I/O | I/O 完成后通知进程 |
## 网络编程
| 英文术语 | 中文术语 | 简要说明 |
|----------|----------|----------|
| Socket | 套接字 | 网络通信的端点 |
| TCP (Transmission Control Protocol) | 传输控制协议 | 可靠的、面向连接的传输协议 |
| UDP (User Datagram Protocol) | 用户数据报协议 | 不可靠的、无连接的传输协议 |
| IP (Internet Protocol) | 网际协议 | 网络层协议 |
| Port | 端口 | 进程的网络标识0~65535 |
| Client | 客户端 | 发起连接的一方 |
| Server | 服务器 | 接受连接的一方 |
| Three-Way Handshake | 三次握手 | TCP 建立连接的过程 |
| Four-Way Termination | 四次挥手 | TCP 断开连接的过程 |
| Byte Order | 字节序 | 大端序与小端序 |
| Network Byte Order | 网络字节序 | 大端序Big-Endian |
| DNS (Domain Name System) | 域名系统 | 主机名到 IP 地址的映射 |
| HTTP (HyperText Transfer Protocol) | 超文本传输协议 | Web 的应用层协议 |
| Concurrent Server | 并发服务器 | 同时处理多个客户端连接 |
| Iterative Server | 迭代服务器 | 一次处理一个客户端连接 |
| Proxy Server | 代理服务器 | 代替客户端向服务器请求 |
## 并发编程
| 英文术语 | 中文术语 | 简要说明 |
|----------|----------|----------|
| Concurrency | 并发 | 多个任务在逻辑上同时推进 |
| Parallelism | 并行 | 多个任务在物理上同时执行 |
| Thread Pool | 线程池 | 预先创建一组线程,重复使用 |
| Prethreading | 预线程化 | 提前创建线程池的技术 |
| Task Queue | 任务队列 | 存储待处理任务的队列 |
| Work Stealing | 工作窃取 | 空闲线程从其他线程获取任务 |
| Scalability | 可扩展性 | 增加资源时性能提升的程度 |
| Speedup | 加速比 | 并行执行时间与串行执行时间的比值 |
| Amdahl's Law | 阿姆达尔定律 | 并行加速的理论上限 |
| Load Balancing | 负载均衡 | 将任务均匀分配到多个处理单元 |
| Thread-Safe | 线程安全 | 函数在多线程环境下正确运行 |
| Reentrant | 可重入 | 函数可被中断后安全重新进入 |

View File

@@ -0,0 +1,239 @@
# 附录C 学习路径指南
> 根据不同背景和目标,定制个性化的操作系统课程学习方案。
---
## 按基础水平定制
### 方案一:有 C 语言基础,无 Linux 经验
**推荐路径:**
```
第01讲 Linux 简介与使用(重点:命令行操作、文件系统)
|
第02讲 Linux 环境 C 编程重点GCC 编译、GDB 调试)
|
第03讲 文件 I/O 编程重点open/read/write、标准 I/O
|
第04讲 进程控制重点fork/exec/wait
|
第05讲 进程间通信(重点:管道、消息队列)
|
第06讲 多线程编程重点pthread、信号量
|
第07讲 网络编程基础重点Socket API、TCP 模型)
|
第08讲 并发网络服务器(重点:多线程服务器)
|
第09讲 操作系统原理(结合实验理解理论)
```
**学习建议:**
- 花 1~2 周熟悉 Linux 命令行,重点掌握 `ls``cd``mkdir``chmod``gcc``gdb`
- 实验一I/O 编程)是基础中的基础,务必扎实掌握
- 每个实验先读懂示例代码,再自己动手修改
---
### 方案二:有 Linux 经验C 语言基础一般
**推荐路径:**
```
第01讲 C 语言回顾(重点:指针、结构体、动态内存)
|
第02讲 文件 I/O重点系统调用 vs 库函数)
|
第03讲 进程控制重点fork 的理解)
|
第04讲 进程间通信
|
第05讲 多线程编程(重点:同步机制)
|
第06讲 网络编程
|
第07讲 并发服务器
|
第08讲 操作系统原理
```
**学习建议:**
- 重点补强 C 语言指针和内存管理
- 实验中遇到的 C 语言问题及时查阅资料
- 可以跳过 Linux 基础操作部分,直接进入编程实验
---
### 方案三:有 C 语言 + Linux 经验
**推荐路径:**
```
快速浏览第01~03讲直接进入实验
|
第04讲 进程控制重点shell 实现、daemon
|
第05讲 进程间通信(重点:共享内存 + 信号量)
|
第06讲 多线程编程(重点:竞态条件、生产者-消费者)
|
第07讲 网络编程重点HTTP 协议、文件传输)
|
第08讲 并发服务器重点预线程化、I/O 多路复用)
|
第09讲 操作系统原理(深入理解调度、内存管理)
```
**学习建议:**
- 可以直接做选做题task43、task54、task66、task67 等)
- 重点理解操作系统原理,将实验经验与理论结合
- 尝试优化代码性能,如并行求和的加速比分析
---
## 按学习目标定制
### 目标一:通过课程考试
**重点内容:**
| 章节 | 考试重点 | 权重 |
|------|----------|------|
| 进程管理 | fork/exec/wait 的工作原理、僵尸进程 | 高 |
| 调度算法 | FCFS、SJF、RR、优先级调度的对比 | 高 |
| 同步互斥 | 信号量、互斥锁、生产者-消费者问题 | 高 |
| 死锁 | 四个必要条件、银行家算法 | 中 |
| 存储管理 | 页式存储、缺页中断、页面置换算法 | 高 |
| 文件系统 | inode、目录结构、磁盘调度 | 中 |
| 网络编程 | TCP 三次握手/四次挥手、Socket 编程流程 | 中 |
**复习策略:**
- 理解概念 > 死记硬背
- 能用代码演示的概念(如 fork、信号量通过实验加深理解
- 算法题要会手动模拟执行过程
- 整理每个章节的核心知识点和易混淆概念
---
### 目标二:提升编程能力
**重点内容:**
| 实验 | 核心技能 | 难度 |
|------|----------|------|
| 实验01 I/O 编程 | 文件读写、结构体序列化 | ★★ |
| 实验02 进程控制 | fork/exec/wait、shell 实现 | ★★★ |
| 实验03 多线程 | pthread、信号量同步 | ★★★★ |
| 实验04 进程间通信 | 管道、消息队列、共享内存 | ★★★ |
| 实验05 网络通信 | Socket 编程、HTTP 协议 | ★★★ |
| 实验06 并发服务器 | 多进程/多线程/预线程化 | ★★★★ |
**练习建议:**
- 每个实验至少完整实现一遍
- 尝试扩展功能(如给 shell 加上后台执行、给服务器加上日志)
- 阅读课程提供的源代码,学习代码风格和错误处理
- 做完必做题后挑战选做题
---
### 目标三:考研准备
**重点理论知识:**
| 主题 | 考点 | 对应章节 |
|------|------|----------|
| 进程与线程 | PCB、进程状态转换、线程模型 | 第04讲 |
| 处理机调度 | 调度算法、周转时间计算 | 第04讲 |
| 进程同步 | 信号量机制、经典同步问题 | 第06讲 |
| 死锁 | 必要条件、预防/避免/检测 | 第04讲 |
| 内存管理 | 分页、分段、虚拟内存、页面置换 | 第05讲 |
| 文件系统 | 目录结构、磁盘调度算法 | 第05讲 |
| I/O 管理 | I/O 控制方式、缓冲技术 | 第03讲 |
**复习策略:**
- 理论与实验结合:用 fork 理解进程创建,用信号量理解同步
- 做历年真题,重点练习算法模拟题(如银行家算法、页面置换)
- 整理易混淆概念对比表(如进程 vs 线程、互斥 vs 同步)
- 用思维导图梳理每章知识结构
---
### 目标四:就业/工程实践
**重点技能:**
| 技能 | 对应内容 | 实用性 |
|------|----------|--------|
| Linux 系统编程 | fork、exec、信号、I/O | 极高 |
| 多线程编程 | pthread、锁、条件变量、线程池 | 极高 |
| 网络编程 | Socket、TCP/UDP、HTTP | 极高 |
| 并发服务器 | 多进程/多线程/事件驱动 | 高 |
| 性能优化 | 加速比分析、I/O 优化 | 中 |
| 系统调试 | GDB、strace、valgrind | 高 |
**实践建议:**
- 所有实验的选做题都值得完成
- 尝试用 epoll 替代 select 实现高性能服务器
- 学习使用 strace 跟踪系统调用,理解程序行为
- 阅读开源项目(如 Nginx、Redis的并发模型
---
## 学习节奏建议
### 16 周学期安排
| 周次 | 内容 | 任务 |
|------|------|------|
| 1~2 | Linux 基础 + C 语言环境 | 熟悉命令行、GCC、GDB |
| 3~4 | I/O 编程 | 完成实验01task41~44 |
| 5~6 | 进程控制 | 完成实验02task51~53 |
| 7~8 | 进程间通信 | 完成实验04task71~73 |
| 9~10 | 多线程编程 | 完成实验03task61~64 |
| 11~12 | 网络编程 | 完成实验05task83~84 |
| 13~14 | 并发服务器 | 完成实验06task92~94 |
| 15~16 | 复习 + 选做实验 | 查漏补缺、挑战选做题 |
### 每周学习建议
- **理论学习2~3 小时):** 阅读课件、理解概念
- **实验编程3~4 小时):** 完成实验任务
- **总结复习1 小时):** 整理笔记、记录疑问
- **总投入:** 每周约 6~8 小时
---
## 常见学习误区
| 误区 | 正确做法 |
|------|----------|
| 只看不写代码 | 动手敲代码,遇到问题再查资料 |
| 直接抄示例代码 | 先理解思路,再自己实现,最后对比优化 |
| 忽略错误处理 | 养成检查返回值、使用 perror 的习惯 |
| 不理解就死记 | fork 的返回值为什么要分两种?理解了就不容易忘 |
| 忽略编译选项 | 理解 `-Wall``-g``-lpthread` 的作用 |
| 不做实验报告 | 写报告的过程就是整理思路的过程 |
| 孤立学习各章节 | 注意知识关联:进程->线程->同步->网络->并发 |
---
## 推荐参考资料
| 类型 | 资源 | 说明 |
|------|------|------|
| 教材 | 《深入理解计算机系统》(CS:APP) | 实验来源,强烈推荐 |
| 教材 | 《Operating System Concepts》 | 操作系统经典教材 |
| 教材 | 《UNIX 环境高级编程》(APUE) | UNIX 编程权威参考 |
| 在线 | CS:APP 官网实验 | CMU 配套实验 |
| 工具 | `man` 手册 | `man 2 fork``man 3 printf` |
| 工具 | `strace` | 跟踪系统调用 |
| 工具 | `valgrind` | 内存泄漏检测 |