这篇来介绍三个比较好玩的头文件: dlfcn.h、sys/mman.h 和 sys/stat.h 。
1. dlfcn.h
定义:
dlfcn.h 是动态链接库函数库的头文件,它提供了一组用于在运行时动态加载和链接共享库(动态链接库或共享对象)的接口。
作用:
允许程序在运行时动态地加载库、获取库中的函数地址以及卸载库。
其中定义的函数:
void *dlopen(const char *filename, int flag): 打开一个动态链接库。
void *dlsym(void *restrict handle, const char *restrict name): 在动态链接库中查找符号(如函数或变量)。
int dlclose(void *handle): 关闭一个动态链接库。
char *dlerror(void): 返回上一个动态链接库错误的字符串描述。
具体用法:
#include <dlfcn.h>
#include <stdio.h>
int main() {
void *handle = dlopen("./libexample.so", RTLD_LAZY);
if (!handle) {
fprintf(stderr, "%s\n", dlerror());
return 1;
}
void (*foo)() = dlsym(handle, "foo");
if (!foo) {
fprintf(stderr, "%s\n", dlerror());
dlclose(handle);
return 1;
}
foo(); // 调用库中的函数
dlclose(handle);
return 0;
}
2. sys/mman.h
定义:
sys/mman.h 是内存映射的头文件,它提供了一组用于内存映射文件或设备的接口。
作用:
允许程序将文件或其他对象映射到进程的地址空间中,从而可以直接通过指针访问这些对象的内容。
其中定义的函数:
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset): 映射文件或设备到内存。
int munmap(void *addr, size_t length): 取消内存映射。
int mprotect(void *addr, size_t len, int prot): 改变已映射内存区域的保护属性。
int msync(void *addr, size_t length, int flags): 同步映射区域与文件或设备的内容。
具体用法:
#include <sys/mman.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main() {
int fd = open("example.txt", O_RDONLY);
if (fd == -1) {
perror("open");
return 1;
}
struct stat sb;
if (fstat(fd, &sb) == -1) {
perror("fstat");
return 1;
}
char *map = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (map == MAP_FAILED) {
perror("mmap");
return 1;
}
printf("%s\n", map);
if (munmap(map, sb.st_size) == -1) {
perror("munmap");
return 1;
}
close(fd);
return 0;
}
3. sys/stat.h
定义:
sys/stat.h 是文件状态的头文件,它提供了一组用于获取和修改文件或文件系统状态信息的接口。
作用:
允许程序查询文件或目录的状态信息,如大小、权限、时间戳等。
其中定义的函数:
int stat(const char *path, struct stat *buf): 获取文件状态。
int fstat(int fd, struct stat *buf): 获取已打开文件的状态。
int lstat(const char *path, struct stat *buf): 获取符号链接本身的状态,而不是链接指向的文件的状态。
结构体 struct stat:
struct stat 是一个结构体,用于存储文件或文件系统的状态信息。其定义在 sys/stat.h 中,具体的字段可能会因操作系统和文件系统类型而异,但通常会包含以下一些字段:
dev_t st_dev: 文件所在设备的标识符。
ino_t st_ino: 文件的 i-node 号。
mode_t st_mode: 文件类型和权限。
nlink_t st_nlink: 文件的硬链接数。
uid_t st_uid: 文件所有者的用户 ID。
gid_t st_gid: 文件所有者的组 ID。
dev_t st_rdev: 如果该文件是一个特殊设备文件,则此字段表示设备类型。
off_t st_size: 文件的大小(以字节为单位)。
blksize_t st_blksize: 文件系统的最佳 I/O 块大小。
blkcnt_t st_blocks: 文件占用的磁盘块数。
time_t st_atime: 文件的最后访问时间。
time_t st_mtime: 文件的最后修改时间。
time_t st_ctime: 文件的最后状态改变时间(例如,权限或所有权改变)。
具体用法:
#include <sys/stat.h>
#include <stdio.h>
int main() {
struct stat buf;
if (stat("example.txt", &buf) == -1) {
perror("stat");
return 1;
}
printf("Size: %lld bytes\n", (long long)buf.st_size);
printf("Last modified: %s", ctime(&buf.st_mtime));
// 检查文件类型
if (S_ISREG(buf.st_mode)) {
printf("example.txt is a regular file.\n");
} else if (S_ISDIR(buf.st_mode)) {
printf("example.txt is a directory.\n");
}
// ... 其他文件类型检查
return 0;
}
在这个例子中,我们使用 stat 函数获取了 example.txt 文件的状态信息,并打印了文件的大小和最后修改时间。我们还检查了文件的类型,看它是否是一个常规文件或一个目录。
sys/stat.h 还定义了一些宏,如 S_ISREG, S_ISDIR 等,用于检查文件类型。这些宏与 st_mode 字段结合使用,可以方便地判断文件是常规文件、目录、符号链接等。
简单来说,sys/mman.h, sys/stat.h 和 dlfcn.h 分别提供了内存映射、文件状态查询和动态链接库加载的接口,使得程序可以在运行时进行更复杂的操作和管理。