Linux系统文件IO函数有哪些?open和close函数的使用方法详解

 更新时间:2026年08月25日 09:59:40   作者:Liuuuu408  
想了解Linux系统文件IO吗?本文详细讲解open、close、read、write、lseek等系统函数的用法,包括文件打开、读写、指针定位和文件拓展技巧,帮助你掌握Linux系统编程的核心知识,轻松处理文件操作

Linux系统文件IO

每个系统都有自己的专属函数,我们习惯称其为系统函数。系统函数并不是内核函数,因为内核函数是不允许用户使用的,系统函数就充当了二者之间的桥梁,这样用户就可以间接的完成某些内核操作了。

在前面介绍了文件描述符,在Linux系统中必须要使用系统提供的IO函数才能基于这些文件描述符完成对相关文件的读写操作。这些Linux系统IO函数和标准C库的IO函数使用方法类似,函数名称也类似,下边开始一一介绍。

1. open/close

1.1 open函数

在Linux系统编程中,open 函数用于打开一个文件,并返回一个文件描述符,该文件描述符在后续的文件操作中被用作文件的标识符。

如果文件不存在,就创建一个新文件, open 函数的原型如下:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

/*
open是一个系统函数, 只能在linux系统中使用, windows不支持
fopen 是标准c库函数, 一般都可以跨平台使用, 可以这样理解:
		- 在linux中 fopen底层封装了Linux的系统API open
		- 在window中, fopen底层封装的是 window 的 api
*/
// 打开一个已经存在的磁盘文件
int open(const char *pathname, int flags);
// 打开磁盘文件, 如果文件不存在, 就会自动创建
int open(const char *pathname, int flags, mode_t mode);

参数介绍:

path 是要打开的文件的路径名。

flags 是打开文件的标志,可以是以下一种或多种标志的组合:

  • O_RDONLY:只读方式打开文件。
  • O_WRONLY:只写方式打开文件。
  • O_RDWR:读写方式打开文件。
  • O_CREAT:如果文件不存在,则创建文件。
  • O_EXCL:与 O_CREAT 一同使用,确保文件不存在(文件存在的话创建失败),避免覆盖已存在的文件。
  • O_TRUNC:如果文件存在,并且以写入方式打开,将文件截断为空。
  • O_APPEND:以追加方式打开文件,即写入数据时将数据添加到文件末尾。

mode 是一个八进制数,指定文件的访问权限(仅在创建新文件时有效)。通常使用 S_IRUSRS_IWUSRS_IXUSR 等宏定义来设置文件权限。

open 函数返回一个非负整数作为文件描述符,如果出错则返回 -1。可以

**使用该文件描述符进行后续的文件读写操作。

**以下是一个简单的例子:

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

int main() {
    int fd;

    // 打开文件 example.txt,如果不存在则创建,以读写方式打开
    fd = open("example.txt", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
    
    if (fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    // 使用文件描述符进行文件操作...

    // 关闭文件
    if (close(fd) == -1) {
        perror("close");
        exit(EXIT_FAILURE);
    }

    return 0;
}

请注意,错误处理是良好程序设计的一部分,上述示例中使用 perror 输出错误信息。

1.2 close函数

通过open函数可以让内核给文件分配一个文件描述符, 如果需要释放这个文件描述符就需要关闭文件。

对应的这个系统函数叫做 close,函数原型如下:

#include <unistd.h>
int close(int fd);
  • 函数参数: fd 是文件描述符, 是open() 函数的返回值
  • 函数返回值: 函数调用成功返回值 0, 调用失败返回 -1

1.3 打开文件

文件open.c

// open.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>

int main()
{
    // 打开文件
    int fd = open("abc.txt", O_RDWR); // 只读打开
    // int fd = open("./new.txt", O_CREAT|O_RDWR, 0664); // 创建新文件
    // int fd = open("./new.txt", O_CREAT|O_EXCL|O_RDWR); // 创建新文件之前, 先检测是否存在
    // 文件存在创建失败, 返回-1, 文件不存在创建成功, 返回分配的文件描述符
    if(fd == -1)
    {
        printf("打开文件失败\n");
    }
    else
    {
        printf("fd: %d\n", fd);
    }

    close(fd);
    return 0;
}

2. read/write

2.1 read

read 函数用于从已打开的文件描述符中读取数据。

其原型如下:

#include <unistd.h>

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

其中:

  • fd 是已打开文件的文件描述符。
  • buf 是用于存放读取数据的缓冲区的指针。
  • count 是要读取的字节数。

read 函数的返回值为实际读取的字节数,如果返回值为0,表示已到达文件末尾。如果返回值为-1,表示发生错误。

2.2 write

write 函数用于将数据写入到文件内部,在通过 open 打开文件的时候需要指定写权限,函数原型如下:

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);

其中:

  • fd 是已打开文件的文件描述符。
  • buf 是包含要写入数据的缓冲区的指针。
  • count 是要写入的字节数。

write 函数的返回值为实际写入的字节数。如果返回值为-1,表示发生错误。

2.3 测试程序(文件拷贝)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>

int main() {
	// 1. 打开存在的文件a.txt, 读这个文件
	int fd1 = open("./a.txt", O_RDONLY);
	if (fd1 == -1) {
		perror("open-readfile");
		return -1;
	}
	// 2. 打开不存在的文件, 将其创建出来, 将从a.txt读出的内容写入这个文件中
	int fd2 = open("copy.txt", O_WRONLY | O_CREAT, 0664);
	if (fd2 == -1) {
		perror("open-writefile");
		return -1;
	}
	// 3. 循环读文件, 循环写文件
	char buf[4096];
	int len = -1;
	while ((len = read(fd1, buf, sizeof(buf))) > 0) {
		// 将读到的数据写到另一个文件中
		write(fd2, buf, len);
	}
	// 4.关闭文件
	close(fd1);
	close(fd2);
	return 0;

}

3. lseek

lseek 函数用于在文件中定位文件偏移量(file offset)。

它的原型如下:

#include <sys/types.h>
#include <unistd.h>

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

参数:

  • fd: 文件描述符, open() 函数的返回值, 通过这个参数定位打开的磁盘文件
  • offset: 偏移量,需要和第三个参数配合使用

whence: 通过这个参数指定函数实现什么样的功能

  • SEEK_SET: 从文件头部开始偏移 offset 个字节
  • SEEK_CUR: 从当前文件指针的位置向后偏移offset个字节
  • SEEK_END: 从文件尾部向后偏移offset个字节

返回值:

  • 成功: 文件指针**从头部开始计算总的偏移量**
  • 失败: -1

3.1 移动文件指针

主要可以进行这三种常用操作:

  • 文件指针移动到文件头部
lseek(fd, 0, SEEK_SET);
  • 得到当前文件指针的位置
lseek(fd, 0, SEEK_CUR);
  • 得到文件总大小
lseek(fd, 0, SEEK_END);

3.2 文件扩展

当我们需要下载很大的文件时, 磁盘紧张, 如果不能马上将文件下载到本地, 磁盘可能会被占用, 这时可以现将字符写入到目标文件中, 让扩展的文件和被下载的文件一样大即可

使用 lseek 函数进行文件拓展必须要满足一下条件:

  • 文件指针必须要偏移到文件尾部之后, 多出来的就需要被填充的部分。
  • 文件拓展之后,必须要使用 write()函数进行一次写操作(写什么都可以,没有字节数要求)。

文件扩展举例:

// lseek.c
// 拓展文件大小
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
    int fd = open("a.txt", O_RDWR);
    if(fd == -1)
    {
        perror("open");
        return -1;
    }

    // 文件拓展, 一共增加了 1001 个字节
    lseek(fd, 1024, SEEK_END);
    write(fd, " ", 1);
        
    close(fd);
    return 0;
}

文件扩展前后文件的大小:

4. truncate/ftruncate

truncate/ftruncate 这两个函数的功能是一样的,可以对文件进行拓展也可以截断文件。使用这两个函数拓展文件比使用lseek要简单。

这两个函数的函数原型如下:

// 拓展文件或截断文件
#include <unistd.h>
#include <sys/types.h>

int truncate(const char *path, off_t length);
	- 
int ftruncate(int fd, off_t length);

参数:

  • path: 要拓展/截断的文件的文件名
  • fd: 文件描述符, open() 得到的
  • length: 文件的最终大小
  • 文件原来size > length,文件被截断, 尾部多余的部分被删除, 文件最终长度为length
  • 文件原来size < length,文件被拓展, 文件最终长度为length

返回值: 成功返回0; 失败返回值-1

truncate() 和 ftruncate() 两个函数的区别在于一个使用文件名一个使用文件描述符操作文件, 功能相同。

不管是使用这两个函数还是使用 lseek() 函数拓展文件,文件尾部填充的字符都是 0。

5. perror

一般当程序出错时, 会有一个错误号, 每个错误号对应着错误信息

得到错误号,去查询对应的头文件是非常不方便的,我们可以通过 perror 函数将错误号对应的描述信息打印出来

#include <stdio.h>
// 参数, 自己指定这个字符串的值就可以, 指定什么就会原样输出, 除此之外还会输出错误号对应的描述信息
void perror(const char *s);	

例子: 在前面几个代码中都用到了perror

出错时的提示是这样的

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Apache开启并实现网站伪静态化的方法

    Apache开启并实现网站伪静态化的方法

    Apache的Mod_Rewrite对URL进行重写,实现网站伪静态化,这里就为大家介绍一下
    2022-08-08
  • 限制 Apache日志文件大小的方法

    限制 Apache日志文件大小的方法

    access.log,件在 WEB 服务器运行一段时间之后会达到几十兆甚至上百兆,如果Apache运行有错误,error.log也会增大到几十兆,我们知道系统读写一个大的文本文件是非常耗内存的,因此限定日志文件大小十分必要。
    2009-04-04
  • linux系统文件共享samba配置教程

    linux系统文件共享samba配置教程

    大家好,本篇文章主要讲的是linux系统文件共享samba配置教程,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2021-12-12
  • Apache Ant自动化脚本入门教程及常用命令介绍

    Apache Ant自动化脚本入门教程及常用命令介绍

    这篇文章主要介绍了Apache Ant自动化脚本入门教程及常用命令介绍的相关资料,需要的朋友可以参考下
    2016-06-06
  • Linux中的进程守护supervisor安装配置及使用

    Linux中的进程守护supervisor安装配置及使用

    supervisor是一个很好的守护程序管理工具,配置方面自动启动,日志输出,自动切割日志等等一系列强大功能,下面是在CentOS下安装使用supervisor的记录,非常不错,感兴趣的朋友跟随小编一起看看吧
    2019-07-07
  • Linux进程状态和优先级的用法及说明

    Linux进程状态和优先级的用法及说明

    文章详细介绍了操作系统中进程状态(运行、阻塞、挂起)的概念及Linux操作系统中的具体状态(R、S、D、T、t、X、Z),解释了进程的运行、阻塞、挂起状态的区别,具体状态标识及操作方法,如使用kill命令或Ctrl+C中断进程等
    2026-04-04
  • apache-zookeeper-3.7.1 安装部署教程

    apache-zookeeper-3.7.1 安装部署教程

    这篇文章主要介绍了apache-zookeeper-3.7.1 安装部署,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-02-02
  • Linux删文件力度过大导致IO占用太高的解决方案

    Linux删文件力度过大导致IO占用太高的解决方案

    这篇文章主要介绍了Linux删文件力度过大导致IO占用太高的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • 阿里云Linux主机安装WDCP管理面板(包含lamp+lnmp+lanmp环境)

    阿里云Linux主机安装WDCP管理面板(包含lamp+lnmp+lanmp环境)

    这篇文章主要介绍了阿里云Linux主机安装WDCP管理面板(包含lamp+lnmp+lanmp环境),需要的朋友可以参考下
    2017-08-08
  • Linux性能监控与调优方式详解

    Linux性能监控与调优方式详解

    本文系统介绍Linux性能监控与调优方法,涵盖CPU、内存、磁盘、网络等指标检测工具及优化策略,如进程绑定、I/O调度调整、TCP缓冲优化等,适用于性能问题诊断与解决
    2025-08-08

最新评论