vault backup: 2026-06-13 23:46:22
This commit is contained in:
360
操作系统/附录/附录A_Wrapper库参考.md
Normal file
360
操作系统/附录/附录A_Wrapper库参考.md
Normal 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)` | 打印应用错误并退出 |
|
||||
Reference in New Issue
Block a user