Files
obsidian/操作系统/附录/附录A_Wrapper库参考.md

11 KiB
Raw Blame History

附录A Wrapper 库参考

概述

Wrapper 库是课程提供的 C 语言工具库,封装了课程用到的所有系统调用。每个 Wrapper 函数在内部调用对应的系统调用并检查返回值,出错时自动打印错误信息并终止程序,从而简化实验代码的编写。

源文件组成:

文件 说明
wrapper.h 头文件,包含所有函数声明、类型定义和常量
wrapper.c Wrapper 函数实现
ptwrapper.c POSIX 线程相关 Wrapper 函数
libwrapper.a 预编译的静态库

编译与使用

# 方法一:链接静态库
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

头文件包含的系统头文件

#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>

常量与类型定义

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 获取当前进程组

示例:

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 获取文件状态

示例:

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 判断信号是否在集合中

示例:

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

示例(生产者-消费者):

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_readnRio_writenRio_readinitbRio_readnbRio_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) 同上(带错误检查)

示例(服务器):

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);

示例(客户端):

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) 打印应用错误并退出