插件窝 干货文章 Linux操作文件的底层系统怎么调用

Linux操作文件的底层系统怎么调用

文件 int 描述 include 449    来源:    2025-04-24

Linux 操作文件的底层系统调用主要通过以下几个核心函数实现,这些函数直接与内核交互,是用户空间程序访问文件系统的桥梁:


1. 文件描述符(File Descriptor)

  • 每个打开的文件对应一个整数文件描述符(fd),是内核维护的打开文件表的索引。
  • 标准文件描述符:
    • 0: 标准输入(STDIN_FILENO)
    • 1: 标准输出(STDOUT_FILENO)
    • 2: 标准错误(STDERR_FILENO)

2. 核心系统调用

打开/创建文件

#include <fcntl.h>
int open(const char *pathname, int flags, mode_t mode);
  • 参数
    • pathname: 文件路径。
    • flags: 打开方式(如 O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_TRUNC 等)。
    • mode: 文件权限(仅 O_CREAT 时生效,如 0644)。
  • 返回:成功返回文件描述符,失败返回 -1

关闭文件

#include <unistd.h>
int close(int fd);

读写文件

ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
  • 参数
    • fd: 文件描述符。
    • buf: 数据缓冲区。
    • count: 读写字节数。
  • 返回:实际读写字节数,失败返回 -1

文件定位

off_t lseek(int fd, off_t offset, int whence);
  • whence
    • SEEK_SET: 文件开头。
    • SEEK_CUR: 当前位置。
    • SEEK_END: 文件末尾。

文件元数据

#include <sys/stat.h>
int stat(const char *pathname, struct stat *buf);
int fstat(int fd, struct stat *buf);
  • 获取文件信息(如大小、权限等),填充到 struct stat 结构体中。

删除文件/目录

int unlink(const char *pathname); // 删除文件
int rmdir(const char *pathname); // 删除空目录

内存映射(高效IO)

#include <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);
  • 将文件映射到内存,直接通过指针操作文件。

3. 文件描述符复制

int dup(int oldfd); // 复制描述符(返回最小可用fd)
int dup2(int oldfd, int newfd); // 强制指定新fd

4. 同步写入(确保数据落盘)

#include <unistd.h>
int fsync(int fd); // 同步文件数据+元数据
int fdatasync(int fd); // 仅同步文件数据

5. 示例代码

#include <fcntl.h>
#include <unistd.h>

int main() {
    int fd = open("test.txt", O_RDWR | O_CREAT, 0644);
    write(fd, "Hello", 5);
    lseek(fd, 0, SEEK_SET);

    char buf[10];
    read(fd, buf, 5);
    close(fd);
    return 0;
}

6. 底层原理

  1. 用户态到内核态切换:通过软中断(如 int 0x80syscall 指令)触发系统调用。
  2. VFS(虚拟文件系统):内核抽象层,统一处理不同文件系统(ext4, NTFS等)。
  3. 页缓存(Page Cache):内核缓存文件数据,减少磁盘IO。

7. 性能与安全提示

  • 减少系统调用:批量读写(如 readv/writev)或使用 mmap
  • 检查返回值:始终处理错误(如 errno)。
  • 文件锁:使用 fcntlflock 避免竞争条件。

通过掌握这些系统调用,可以深入理解Linux文件操作的底层机制,并编写高效、可靠的代码。