当前位置: 首页 > article >正文

【Linux文件IO】系统IO详情

目录

一、前言

二、相关API介绍

2.1 open

2.2 read

2.3 write

2.4 lseek

2.5 close

三、简单示例

3.1 示例1

3.2 示例2


一、前言

在 Linux 系统编程中,系统 I/O(又称低级 I/O)是直接通过操作系统提供的系统调用实现的文件操作接口。本文主要讲解open、read、write、lseek、close的功能以及用法。

二、相关API介绍

2.1 open

函数原型

int open(const char*pathname,int flags,mode_t mode);

函数功能:打开或创建文件,返回文件描述符。

参数说明

1.pathname

要打开或者创建的目标文件

2.flags

打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成falgs。

参数

作用

O_RDONLY

只读(前三个三选一)

O_WRONLY

只写(前三个三选一)

O_RDWR

读写(前三个三选一)

O_CREAT

若文件不存在,则创建它,需要使用mode选项来指明新文件的访问权限

O_APPEND

追加写入

O_TRUNC

若文件存在则覆盖(清空文件内容)

3.mode

新建文件时,要指明的文件访问权限。如果文件不存在且flags包含O_CREAT,mode参数决定新文件的权限;若文件已存在,mode会被忽略。未设置O_CREAT时,mode参数即使存在也不会被使用。

通过3位八进制数表示权限,每位对应“所有者-组-其他用户”的权限总和:

  • 4:读(Read)
  • 2:写(Write)
  • 1:执行(Execute)

示例:

  • 0644:所有者读写(6=4+2),组和其他用户只读(4)。
  • 注意:数值前的0表示八进制格式,而非权限修饰符。

函数返回值

成功:新打开的文件描述符

失败:-1

open返回的文件描述符一定是最小的而且没有被使用的。

示例

int fd = open("test.txt", O_RDWR | O_CREAT, 0644);

注意点

  1. 实际权限 = mode & ~umask

umask是进程的默认权限掩码(如0022),用于屏蔽某些权限位。例如:若mode=0666(期望权限rw-rw-rw-),umask=0022,最终权限为0644(rw-r--r--) 。可通过umask(0)临时禁用掩码,强制使用mode的原始值 1。

  1. 即使创建文件时设置了权限(如0555禁止写),后续通过open返回的文件描述符仍可修改文件内容(权限检查仅在open时进行)。
  2. 权限的继承性:目录的权限影响其子文件的创建。若父目录无写权限,即使mode允许,也无法创建文件。

2.2 read

函数原型

ssize_t read(int fd, void * buf, size_t count);

函数功能:从文件描述符对应的文件中读取数据到缓冲区。

参数说明

  • fd:文件描述符。
  • buf:存储数据的缓冲区地址。
  • count:期望读取的字节数。

函数返回值

成功:读到的字节数

已到达文件尾:0

失败:-1

示例

char buffer[1024];
ssize_t bytes_read = read(fd, buffer, sizeof(buffer));

2.3 write

函数原型

ssize_t write (int fd, const void * buf, size_t count);

函数功能:将缓冲区数据写入文件描述符对应的文件。

参数说明

跟read类似

函数返回值

成功:已写入的字节数

失败:-1

示例

const char *data = "Hello, Linux!";
ssize_t bytes_written = write(fd, data, strlen(data));

2.4 lseek

函数原型

off_t lseek(int fd, off_t offset, int whence);

函数功能:调整文件读写指针的位置,支持随机访问。

参数说明

1.fd

文件描述符。

2.offset

偏移量,正前移,负后移。

3.whence

当前位置的基点

  • SEEK_SET:文件的开头
  • SEEK_CUR:文件指针的位置
  • SEEK_END:文件结尾

函数返回值

成功:文件当前位移

失败:-1

示例

off_t new_pos = lseek(fd, 0, SEEK_END); // 移动到文件末尾

2.5 close

函数原型

int close(int fd)

函数功能:关闭文件描述符,释放系统资源。

参数说明

1.fd

需要关闭的文件描述符。

函数返回值

成功:返回0;

失败:返回-1,并设置errno

示例

close(fd);

注意点

程序结束时未关闭的文件可能导致资源泄漏,但内核会自动关闭。

三、简单示例

3.1 示例1

功能:写入一定数据,然后在读取这些数据。其中涉及到文件指针的问题,中间也涉及到关不关闭文件描述符。

/*********************************************************************
 * 版权所有: Copyright (c) 2023-2024  XXX Company. All rights reserved.
 * 系统名称: 
 * 文件名称: main.c
 * 内容摘要: open write lseek read close函数的应用
 * 当前版本: 
 * 作    者: nebula嵌入式
 * 设计日期: 2023-01-21 15:58
 * 修改记录: 
 * 日    期          版    本          修改人          修改摘要
**********************************************************************/
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include<unistd.h>

int main(int argc, char *argv[])
{
    int fd, num;
    fd = open("a.txt", O_RDWR|O_CREAT|O_TRUNC, 0777);
    printf("fd=%d\n", fd);
    printf("hello world!!!\n");
    num = write(fd, "this is demo!", strlen("this is demo!"));
    if(num>0)
    {
        printf("data is save!\n");
    }else
    {
        printf("data save failed!");
    }
    printf("num=%d\n", num);
    lseek(fd, -num, SEEK_CUR);
    int len;
    char str[50]="";
    len = read(fd, str, num);
    printf("len=%d\n", len);
    if(len>0)
    {
        printf("txt content:%s\n", str);
    }else if(len<0)
    {
        printf("content read failed!");
    }else
    {
        printf("read over!\n");
    }
    close(fd);
    return 0;
}

3.2 示例2

功能:指定路径拷贝文件。

/*********************************************************************
 * 版权所有: Copyright (c) 2023-2024  XXX Company. All rights reserved.
 * 系统名称: 
 * 文件名称: main.c
 * 内容摘要: 简单的文件拷贝程序
 * 当前版本: 
 * 作    者: nebula嵌入式
 * 设计日期: 2025-03-01 15:11
 * 修改记录: 
 * 日    期          版    本          修改人          修改摘要
**********************************************************************/
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include<unistd.h>

int main(int argc, char *argv[])
{
    int source_fd = -1, des_fd = -1;
    int ret = 0, file_size = 0;
    char buf[1024] = {0};

    if (argc != 3) {
        printf("missing parameter!\n");
        printf("./program source_addr des_addr\n");
        return -1;
    }

    des_fd = open(argv[2], O_RDWR|O_CREAT|O_TRUNC, 0777);
    if(des_fd < 0){
        printf("open des fd failed!\n");
        close(des_fd);
        return -1;
    }

    source_fd = open(argv[1], O_RDONLY);
    if(source_fd < 0){
        printf("open source fd failed!\n");
        close(source_fd);
        return -1;
    }

    while((ret = read(source_fd, buf, sizeof(buf) - 1)) > 0){
        file_size += ret;
        if (write(des_fd, buf, ret) != ret) {
            perror("写入文件失败");
            break;
        }
    }

    if (ret < 0) {
        perror("读取文件失败");
    }

    printf("文件拷贝完成,共拷贝了 %d 字节\n", file_size);

        close(source_fd);
        close(des_fd);

    return 0;
}
./a.out cp_source_test.txt cp_des_test.txt


http://www.kler.cn/a/569221.html

相关文章:

  • torch.einsum 的 10 个常见用法详解以及多头注意力实现
  • Android SystemUI深度定制实战:下拉状态栏集成响铃功能开关全解析
  • 图像分类项目1:基于卷积神经网络的动物图像分类
  • 【AI实践】xiaozhi-esp32虾哥开源版-分析
  • PyTorch 中的 nn.ModuleList 是什么?与普通列表有啥区别?
  • C#调用CANoeCLRAdapter.dll文章(一)
  • Go语言学习笔记(六)——标准库
  • 算法系列之双指针(待完善题目)
  • openssl下aes128算法xts模式加解密运算实例
  • MySQL零基础教程13—分组查询(group by 和 having)
  • 消息中间件应用的常见问题与方案?
  • 华为 Open Gauss 数据库在 Spring Boot 中使用 Flyway
  • 【Delphi】如何解决使用webView2时主界面置顶,而导致网页选择文件对话框被覆盖问题
  • Python的那些事第三十四篇:基于 Plotly 的交互式图表与仪表板设计与应用
  • 【北京迅为】itop-3568 开发板openharmony鸿蒙烧写及测试-第1章 体验OpenHarmony—烧写镜像
  • 6-2JVM解释器
  • docker利用docker-compose-gpu.yml启动RAGFLOW,文档解析出错【亲测已解决】
  • 高效API开发:FastAPI中的缓存技术与性能优化
  • 前缀和算法 算法4
  • unsloth报错FileNotFoundError: [WinError 3] 系统找不到指定的路径。