【Linux系统】文件IO

Linux 文件与目录(文件IO)操作

Linux 文件与目录操作(文件 I/O)是Linux 系统编程中最基础、也是最重要的部分之一,几乎所有系统调用都会涉及文件描述符、文件操作或目录。

1. 一切皆文件(Everything is a file)

在 Linux 中,几乎所有系统资源都被看作"文件":

  • 普通文件(text、binary)
  • 目录
  • 设备文件(如 /dev/sda/dev/tty0
  • 套接字(socket)
  • 管道(pipe)

Linux 内核通过一个 文件描述符 (file descriptor, FD) 来引用打开的文件资源。

2. 文件描述符

  • 文件描述符是一个整数,从 0 开始编号。

  • 默认情况下,Linux 会自动为每个进程打开三个文件描述符,三个文件描述符分别对应如下:

    文件描述符 含义
    STDIN_FILENO (0) 标准输入(stdin)
    STDOUT_FILENO (1) 标准输出(stdout)
    STDERR_FILENO (2) 标准错误(stderr)

当你使用 open() 打开一个文件时,系统会返回一个新的文件描述符,如:3、4、5 等。

一、文件操作系统调用

文件操作的系统调用函数都在头文件 <fcntl.h>, <unistd.h>, <sys/stat.h> 中定义。

1. 打开文件 open()

c 复制代码
int open(const char *pathname, int flags, mode_t mode);
  • path:文件路径
  • flags:打开方式,如 O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_APPEND
  • mode:创建文件时的权限(如 0644

示例:

c 复制代码
#include <fcntl.h>
#include <stdio.h>

int fd = open("test.txt", O_RDWR | O_CREAT, 0644);
if (fd == -1) {
    perror("open");   // perror 在stdio.h中声明
}

2. 读写文件 read() / write()

c 复制代码
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
  • 返回值是实际读/写的字节数。
  • 返回 0 表示文件结束(EOF)。

示例(从文件读取一段内容):

c 复制代码
char buffer[128];
ssize_t n = read(fd, buffer, sizeof(buffer));
if (n > 0) {
    write(STDOUT_FILENO, buffer, n); // 输出到终端
}

3. 文件偏移与定位 lseek()

c 复制代码
off_t lseek(int fd, off_t offset, int whence);
  • offset:偏移量。

  • whence

    可取:

    • SEEK_SET:从文件开头偏移 offset
    • SEEK_CUR:从当前位置偏移
    • SEEK_END:从文件末尾偏移

示例(计算文件大小):

c 复制代码
off_t size = lseek(fd, 0, SEEK_END);
printf("File size: %ld bytes\n", size);

4. 关闭文件 close()

c 复制代码
int close(int fd);
  • 程序结束前要关闭打开的文件,释放资源。

5. 文件状态 stat()

c 复制代码
int stat(const char *path, struct stat *st);
  • 用于获取文件的元信息(权限、大小、时间、类型等)。

示例:

c 复制代码
struct stat st;
if (stat("test.txt", &st) == 0) {
    printf("Size: %ld, Mode: %o\n", st.st_size, st.st_mode);
}

示例程序:

c 复制代码
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>

int main() {
    char buff[10] = {0};
    printf("pid = %d\n", getpid());
    int fd = open("test.txt", O_RDWR | O_CREAT, 0644);
    if (fd == -1) {
        perror("open");  // perror在stdio.h头文件中声明
    }
    printf("fd = %d\n", fd);
    ssize_t read_len =  read(fd, buff, sizeof(buff));
    if (read_len == -1) {
        perror("read");
    }else if (read_len == 0) {
        perror("EOF");
    }
    /* 输出到终端 */
    ssize_t len =  write(STDOUT_FILENO, buff, sizeof(buff));
    printf("\noutput len = %ld\n",len);

    /* 偏移到文件结尾,计算文件大小 */
    off_t size = lseek(fd, 0, SEEK_END);
    printf("File size: %ld bytes\n", size);
    char str[] = "Hello World";
    /* 在文件结尾写入字符串 */
    write(fd, str, strlen(str));
    close(fd);

    struct stat st;   // stat 位于 <sys/stat.h> 中
    if (stat("test.txt", &st) == 0) {
        printf("Size: %ld, Mode: %o\n", st.st_size, st.st_mode);
    }
    return 0;
}

输出:

c 复制代码
1234567890
output len = 10
File size: 11 bytes
Size: 22, Mode: 100644
相关推荐
星恒讯工业路由器18 小时前
新一代通信网:从“连接万物”到“智联万物”的关键跃迁
网络·物联网·智能路由器·工业路由器·工业物联网·5g-a·新一代通信网
comedate18 小时前
Windows / Linux GPU 虚拟内存布局差异与 CUDA 越界访问行为
linux·windows·mmu·cuda 越界访问
暴力求解20 小时前
Linux网络---传输层协议TCP(二)
linux·服务器·开发语言·网络·tcp/ip
ltl21 小时前
序列化格式深度对比:Protobuf、FlatBuffers、Cap’n Proto
linux
lengjingzju21 小时前
编译与调试完全指南—第17章 总结
linux
ltl21 小时前
容器网络性能真相:veth vs macvlan vs eBPF 数据面
linux
数字化转型分享点滴1 天前
机加工车间上线 SH‑AIOT 物联网会遇到哪些常见实施难点
python·物联网
我不会插花弄玉1 天前
9.进程间通信(上)【由浅入深-Linux】
linux·共享内存·进程通信
鲁邦通物联网1 天前
出海物联网设备的全球化网络接入与合规脱敏架构:基于 Node-RED 与 C++ 零拷贝的边缘系统设计
网络·物联网·系统架构·边缘计算·边缘计算网关·5g数采·工业级边缘计算网关
星恒讯工业路由器1 天前
家庭无线组网方式全解析:从单路由到FTTR,哪种适合你?
网络·物联网·智能路由器·路由器·家庭组网·ac+ap·mesh组网