1、open():用于打开或创建一个文件。
2、close():用于关闭一个打开的文件。
3、read():用于从文件中读取数据。
4、write():用于向文件中写入数据。
5、lseek():用于移动文件读写位置。
6、opendir():用于打开一个目录流,用于后续的目录操作。
7、readdir():用于读取目录流中的下一个条目。
8、closedir():用于关闭目录流。
9、chmod():用于改变文件的权限。
10、stat():用于获取文件或目录的状态信息。
11、lstat():用于获取符号链接本身的状态信息(不跟随符号链接)。
12、静态库相关
13、动态库相关
用于打开或创建一个文件
int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode);
pathname
:文件路径名。
flags
:文件打开方式,如只读(O_RDONLY)、只写(O_WRONLY)、读写(O_RDWR)等。还可以包含文件创建标志(O_CREAT)、追加模式(O_APPEND)等。
mode
:如果文件不存在且指定了 O_CREAT 标志,则按照该模式创建文件,如 0666(所有用户可读可写)。
#include
#include#include #include int main() { int fd = open("test.txt", O_RDWR | O_CREAT, 0666); if (fd == -1) { perror("open failed"); return 1; } write(fd, "Hello, World!", 13); close(fd); return 0; }
关闭一个打开的文件
int close(int fd);
fd
:文件描述符,即通过 open() 函数返回的文件标识。
#include
#include#include #include int main() { int fd = open("test.txt", O_RDONLY); if (fd == -1) { perror("open failed"); return 1; } close(fd); printf("File closed successfully\n"); return 0; }
从文件中读取数据
ssize_t read(int fd, void *buf, size_t count);
fd
:文件描述符。
buf
:存储读取数据的缓冲区。
count
:要读取的字节数。
#include
#include#include #include int main() { int fd = open("test.txt", O_RDONLY); if (fd == -1) { perror("open failed"); return 1; } char buf[1024]; ssize_t bytes_read = read(fd, buf, 1024); if (bytes_read == -1) { perror("read failed"); close(fd); return 1; } buf[bytes_read] = '\0'; printf("Content: %s\n", buf); close(fd); return 0; }
向文件中写入数据
ssize_t write(int fd, const void *buf, size_t count);
fd
:文件描述符。
buf
:要写入的数据缓冲区。
count
:要写入的字节数。
#include
#include#include #include int main() { int fd = open("test.txt", O_WRONLY | O_CREAT, 0666); if (fd == -1) { perror("open failed"); return 1; } ssize_t bytes_written = write(fd, "Hello, World!", 13); if (bytes_written == -1) { perror("write failed"); close(fd); return 1; } printf("Bytes written: %zd\n", bytes_written); close(fd); return 0; }
移动文件读写位置
off_t lseek(int fd, off_t offset, int whence);
fd
:文件描述符。
offset
:偏移量,以字节为单位。
whence
:偏移基准,可以是文件开头(SEEK_SET)、当前位置(SEEK_CUR)或文件末尾(SEEK_END)。
#include
#include#include #include int main() { int fd = open("test.txt", O_RDWR | O_CREAT, 0666); if (fd == -1) { perror("open failed"); return 1; } write(fd, "Hello, World!", 13); off_t pos = lseek(fd, 0, SEEK_END); if (pos == -1) { perror("lseek failed"); close(fd); return 1; } printf("File size: %ld bytes\n", pos); close(fd); return 0; }
打开一个目录流,用于后续的目录操作
DIR *opendir(const char *name);
name
:目录路径。
成功时返回一个指向DIR
结构体的指针,失败时返回NULL
。
#include
#include#include int main() { DIR *dir = opendir("."); if (dir == NULL) { perror("opendir failed"); return 1; } struct dirent *entry; while ((entry = readdir(dir)) != NULL) { printf("File: %s\n", entry->d_name); } closedir(dir); return 0; }
读取目录流中的下一个条目
struct dirent *readdir(DIR *dirp);
dirp
:目录流指针,由opendir()
返回。
成功时返回一个指向struct dirent
结构体的指针,到达目录末尾或失败时返回NULL
。
#include
#include#include int main() { DIR *dir = opendir("."); if (dir == NULL) { perror("opendir failed"); return 1; } struct dirent *entry; while ((entry = readdir(dir)) != NULL) { printf("File: %s\n", entry->d_name); } closedir(dir); return 0; }
关闭目录流
int closedir(DIR *dirp);
dirp
:目录流指针,由opendir()
返回。
成功时返回0,失败时返回-1。
#include
#include#include int main() { DIR *dir = opendir("."); if (dir == NULL) { perror("opendir failed"); return 1; } struct dirent *entry; while ((entry = readdir(dir)) != NULL) { printf("File: %s\n", entry->d_name); } if (closedir(dir) == -1) { perror("closedir failed"); return 1; } return 0; }
改变文件的权限
int chmod(const char *path, mode_t mode);
path
:文件路径。
mode
:新的权限模式。
成功时返回0,失败时返回-1。
#include
#include#include int main() { if (chmod("test.txt", 0644) == -1) { perror("chmod failed"); return 1; } printf("File permissions changed successfully\n"); return 0; }
获取文件或目录的状态信息
int stat(const char *path, struct stat *buf);
path
:文件或目录路径。
buf
:用于存储状态信息的struct stat
结构体的指针。用于存储文件或目录的状态信息。它包含了许多关于文件的详细信息,struct stat
的结构体定义通常如下:
struct stat { dev_t st_dev; // 文件所在的设备ID ino_t st_ino; // 文件的inode节点号 mode_t st_mode; // 文件的类型和权限 【详情如下】 nlink_t st_nlink; // 硬链接数 uid_t st_uid; // 文件所有者的用户ID gid_t st_gid; // 文件所有者的组ID dev_t st_rdev; // 如果是特殊文件,设备ID off_t st_size; // 文件大小,以字节为单位 blksize_t st_blksize; // 文件系统的块大小 blkcnt_t st_blocks; // 文件占用的块数 time_t st_atime; // 最后访问时间 time_t st_mtime; // 最后修改时间 time_t st_ctime; // 最后状态改变时间 };
st_mode
:文件的类型和权限。
文件类型可以通过以下宏来判断:
S_ISDIR(mode)
:是否是目录。
S_ISREG(mode)
:是否是普通文件。
S_ISLNK(mode)
:是否是符号链接。
S_ISCHR(mode)
:是否是字符设备。
S_ISBLK(mode)
:是否是块设备。
S_ISFIFO(mode)
:是否是命名管道(FIFO)。
S_ISSOCK(mode)
:是否是套接字。
文件权限可以用以下宏来判断:
S_IRUSR
:用户可读。
S_IWUSR
:用户可写。
S_IXUSR
:用户可执行。
S_IRGRP
:组可读。
S_IWGRP
:组可写。
S_IXGRP
:组可执行。
S_IROTH
:其他用户可读。
S_IWOTH
:其他用户可写。
S_IXOTH
:其他用户可执行。
成功时返回0,失败时返回-1。
#include#include
#include#include #include int main() { struct stat buf; if (stat("test.txt", &buf) == -1) { perror("stat failed"); return 1; } printf("File size: %ld bytes\n", buf.st_size); printf("File type: "); if (S_ISREG(buf.st_mode)) { printf("Regular file\n"); } else if (S_ISDIR(buf.st_mode)) { printf("Directory\n"); } else { printf("Other type\n"); } return 0; }
#include#include #include #include int main() { struct stat buf; const char *filename = "test.txt"; if (stat(filename, &buf) == -1) { perror("stat failed"); return 1; } printf("File: %s\n", filename); printf("Size: %ld bytes\n", buf.st_size); printf("Type: "); if (S_ISDIR(buf.st_mode)) { printf("Directory\n"); } else if (S_ISREG(buf.st_mode)) { printf("Regular file\n"); } else if (S_ISLNK(buf.st_mode)) { printf("Symbolic link\n"); } else { printf("Other type\n"); } printf("Permissions: "); printf("%s", (buf.st_mode & S_IRUSR) ? "r" : "-"); printf("%s", (buf.st_mode & S_IWUSR) ? "w" : "-"); printf("%s", (buf.st_mode & S_IXUSR) ? "x" : "-"); printf("%s", (buf.st_mode & S_IRGRP) ? "r" : "-"); printf("%s", (buf.st_mode & S_IWGRP) ? "w" : "-"); printf("%s", (buf.st_mode & S_IXGRP) ? "x" : "-"); printf("%s", (buf.st_mode & S_IROTH) ? "r" : "-"); printf("%s", (buf.st_mode & S_IWOTH) ? "w" : "-"); printf("%s\n", (buf.st_mode & S_IXOTH) ? "x" : "-"); printf("Last access time: %s", ctime(&buf.st_atime)); printf("Last modification time: %s", ctime(&buf.st_mtime)); printf("Last status change time: %s", ctime(&buf.st_ctime)); return 0; }
获取符号链接本身的状态信息(不跟随符号链接)
int lstat(const char *path, struct stat *buf);
path
:文件或目录路径。
buf
:用于存储状态信息的struct stat
结构体的指针。
成功时返回0,失败时返回-1。
#include#include
#include#include #include int main() { struct stat buf; if (lstat("symlink", &buf) == -1) { perror("lstat failed"); return 1; } printf("Symbolic link points to: %s\n", buf.st_size); printf("File type: "); if (S_ISREG(buf.st_mode)) { printf("Regular file\n"); } else if (S_ISDIR(buf.st_mode)) { printf("Directory\n"); } else { printf("Other type\n"); } return 0; }
DIR *opendir(const char *name);
struct dirent *readdir(DIR *dirp);
int closedir(DIR *dirp);
int chmod(const char *path, mode_t mode);
int stat(const char *path, struct stat *buf);
int lstat(const char *path, struct stat *buf);
文件后缀为 .a
。
在编译时将代码直接链接到可执行文件中。
优点:可执行文件独立运行,无需依赖外部库。
缺点:可执行文件体积较大,更新库时需重新编译。
步骤:
1、编写库文件代码,编译为.o 目标文件。
2、 ar 命令 创建 libxxxx.a 文件 【 ar -rsv libxxxx.a xxxx.o】
3、链接静态库:【gcc -o 目标文件 源码.c -L路径 -lxxxx】 -L 表示库所在的路径 -l 后面跟库的名称
注: 静态库名字要以lib开头,后缀名为.a 。 没有main函数的.c 文件不能生成可执行文件。
假设我们有一个简单的数学运算库,包含加法和乘法功能。
文件结构:
mylib/ ├── mathlib.h ├── add.c └── mul.c
mathlib.h
// mathlib.h int add(int a, int b); int mul(int a, int b);
add.c
// add.c #include "mathlib.h" int add(int a, int b) { return a + b; }
mul.c
// mul.c #include "mathlib.h" int mul(int a, int b) { return a * b; }
.o
目标文件gcc -c add.c mul.c
这会生成 add.o
和 mul.o
。
ar
命令创建静态库ar -rsv libmathlib.a add.o mul.o
这会生成一个静态库文件 libmathlib.a
。
main.c
// main.c #include "mathlib.h" #include int main() { printf("Addition: %d\n", add(5, 3)); // 输出 8 printf("Multiplication: %d\n", mul(5, 3)); // 输出 15 return 0; }
gcc -o main main.c -L. -lmathlib
-L.
表示库文件在当前目录。
-lmathlib
表示链接的静态库名称为 libmathlib.a
。
./main
输出:
Addition: 8 Multiplication: 15
文件后缀为 .so
。
在运行时加载库文件。
优点:可执行文件体积小,多个程序可共享同一份库文件。
缺点:运行时需要确保库文件存在且路径正确。
步骤:
1、生成位置无关代码的目标文件【gcc -c -fPIC xxx.c xxxx.c ....】
2、生成动态库 【gcc -shared -o libxxxx.so xxx.o xxx.o ....】
3、编译可执行文件【gcc -o 目标文件 源码.c -L路径 -lxxxx】
注:执行动态库的可执行文件错误
./test: error while loading shared libraries: libmyheby.so: cannot open shared object file: No such file or directory 错误原因 :可执行文件所使用的动态库找不到
【解决办法】:
1、找到动态库,添加到/usr/lib里面(不建议)
2、使用【export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:你的动态库目录】(临时生效,新窗口都无效)
3、添加【export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:你的动态库目录】在~/.bashrc 文件里面 ,使用source ~/.bashrc 全部生效。
使用上述相同的 mathlib.h
、add.c
和 mul.c
文件。
gcc -c -fPIC add.c mul.c
这会生成 add.o
和 mul.o
。
gcc -shared -o libmathlib.so add.o mul.o
这会生成一个动态库文件 libmathlib.so
。
main.c
// main.c #include "mathlib.h" #include int main() { printf("Addition: %d\n", add(5, 3)); // 输出 8 printf("Multiplication: %d\n", mul(5, 3)); // 输出 15 return 0; }
gcc -o main main.c -L. -lmathlib
运行程序时可能会提示动态库找不到,解决方法如下:
方法 1:临时设置环境变量
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. ./main
方法 2:永久设置环境变量
echo 'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.' >> ~/.bashrc source ~/.bashrc ./main
./main
输出:
Addition: 8 Multiplication: 15
ldd main
这会列出 main
所依赖的所有动态库。
【有错请留言谢谢】