【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
相关推荐
刘某的Cloud4 小时前
ceph设置标志位
linux·运维·ceph·openstack
monkeyhlj4 小时前
excel-mcp-server rocky linux简单部署
linux·运维·excel
liulilittle4 小时前
HI3798MV100 运营商机顶盒NAS LINUX OS - IP地址静态绑定指南
linux·运维·服务器·网络·tcp/ip·nas·机顶盒
zhong_kh5 小时前
RHCSA 基础练习
linux
冷崖5 小时前
定时器的学习(二)
linux·c++·学习
馨谙6 小时前
chage -d 0 强制密码修改的完整流程
linux·运维
爱技术的小伙子6 小时前
【Linux运维】 Prometheus + Grafana + Alertmanager 监控系统部署指南(CentOS & Ubuntu 通用版)
linux·运维·prometheus
Zach_yuan6 小时前
Linux编辑器vim
linux·编辑器·vim
riveting6 小时前
48 元四核 ARM 核心板!明远智睿 2351 进入嵌入式市场
物联网·智能家居·嵌入式开发·明远智睿·2351核心板