跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C

Linux 文件操作:系统调用与标准库函数接口汇总及代码示例

Linux 文件操作涉及系统调用与标准库函数。系统调用如 open、read、write 直接操作内核文件描述符,效率高但需手动管理;标准库函数如 fopen、fread、fwrite 提供缓冲区和便捷接口。汇总了常用接口参数与返回值,并通过代码演示了文件打开方式、重定向机制、缓冲区原理以及简易 stdio 实现,帮助理解底层 IO 模型。

星云发布于 2026/2/7更新于 2026/7/1037 浏览
Linux 文件操作:系统调用与标准库函数接口汇总及代码示例

Linux 文件操作:系统调用与标准库函数接口汇总及代码示例

1. 文件操作的系统调用和库函数各个接口

1.1 C 语言文件操作常用接口

函数名功能头文件参数说明
fopen打开文件stdio.hFILE* fopen(const char* filename, const char* mode)
fclose关闭文件stdio.hint fclose(FILE* stream)
fputc写入一个字符stdio.hint fputc(int char, FILE* stream)
fgetc读取一个字符stdio.hint fgetc(FILE* stream)
fputs写入一个字符串stdio.hint fputs(const char* str, FILE* stream)
fgets读取一个字符串stdio.hchar* fgets(char* str, int n, FILE* stream)
fprintf格式化写入数据stdio.hint fprintf(FILE* stream, const char* format, ...)
fscanf格式化读取数据stdio.hint fscanf(FILE* stream, const char* format, ...)
fwrite向二进制文件写入数据stdio.hsize_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream)
fread从二进制文件读取数据stdio.hsize_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream)
fseek设置文件指针的位置stdio.hint fseek(FILE* stream, long int offset, int whence)
ftell计算当前文件指针相对于起始位置的偏移量stdio.hlong int ftell(FILE* stream)
rewind设置文件指针到文件的起始位置stdio.hvoid rewind(FILE* stream)
ferror判断文件操作过程中是否发生错误stdio.hint ferror(FILE* stream)
feof判断文件指针是否读取到文件末尾stdio.hint feof(FILE* stream)

1.2 系统调用和库函数汇总

1.2.1 系统调用
系统调用函数功能头文件参数模板返回值
open()打开或创建文件<fcntl.h>int open(const char *pathname, int flags, mode_t mode);文件描述符 (成功)/-1(失败)
creat()创建新文件<fcntl.h>int creat(const char *pathname, mode_t mode);文件描述符 (成功)/-1(失败)
close()关闭文件描述符<unistd.h>int close(int fd);0(成功)/-1(失败)
read()从文件描述符读取数据<unistd.h>ssize_t read(int fd, void *buf, size_t count);读取字节数/-1(失败)
write()向文件描述符写入数据<unistd.h>ssize_t write(int fd, const void *buf, size_t count);写入字节数/-1(失败)
lseek()移动文件读写指针<unistd.h>off_t lseek(int fd, off_t offset, int whence);新偏移量/-1(失败)
pread()从指定偏移处读取<unistd.h>ssize_t pread(int fd, void *buf, size_t count, off_t offset);读取字节数/-1(失败)
pwrite()向指定偏移处写入<unistd.h>ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);写入字节数/-1(失败)
fsync()将文件数据同步到磁盘<unistd.h>int fsync(int fd);0(成功)/-1(失败)
fdatasync()同步文件数据(不包括元数据)<unistd.h>int fdatasync(int fd);0(成功)/-1(失败)
ftruncate()截断/扩展文件大小<unistd.h>int ftruncate(int fd, off_t length);0(成功)/-1(失败)
dup()复制文件描述符<unistd.h>int dup(int oldfd);新文件描述符/-1(失败)
dup2()复制文件描述符到指定值<unistd.h>int dup2(int oldfd, int newfd);新文件描述符/-1(失败)
fcntl()文件描述符控制操作<fcntl.h>int fcntl(int fd, int cmd, ... /* arg */);依赖 cmd/-1(失败)
ioctl()设备 I/O 控制<sys/ioctl.h>int ioctl(int fd, unsigned long request, ...);依赖 request/-1(失败)
mmap()内存映射文件<sys/mman.h>void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);映射地址/MAP_FAILED
munmap()解除内存映射<sys/mman.h>int munmap(void *addr, size_t length);0(成功)/-1(失败)
mprotect()修改内存保护属性<sys/mman.h>int mprotect(void *addr, size_t len, int prot);0(成功)/-1(失败)
msync()同步内存映射到文件<sys/mman.h>int msync(void *addr, size_t length, int flags);0(成功)/-1(失败)
stat()获取文件状态信息<sys/stat.h>int stat(const char *pathname, struct stat *statbuf);0(成功)/-1(失败)
fstat()通过 fd 获取文件状态<sys/stat.h>int fstat(int fd, struct stat *statbuf);0(成功)/-1(失败)
lstat()获取符号链接状态<sys/stat.h>int lstat(const char *pathname, struct stat *statbuf);0(成功)/-1(失败)
access()检查文件访问权限<unistd.h>int access(const char *pathname, int mode);0(成功)/-1(失败)
chmod()修改文件权限<sys/stat.h>int chmod(const char *pathname, mode_t mode);0(成功)/-1(失败)
fchmod()通过 fd 修改文件权限<sys/stat.h>int fchmod(int fd, mode_t mode);0(成功)/-1(失败)
chown()修改文件所有者<unistd.h>int chown(const char *pathname, uid_t owner, gid_t group);0(成功)/-1(失败)
fchown()通过 fd 修改文件所有者<unistd.h>int fchown(int fd, uid_t owner, gid_t group);0(成功)/-1(失败)
readlink()读取符号链接目标<unistd.h>ssize_t readlink(const char *pathname, char *buf, size_t bufsiz);读取字节数/-1(失败)
rename()重命名/移动文件<stdio.h>int rename(const char *oldpath, const char *newpath);0(成功)/-1(失败)
mkdir()创建目录<sys/stat.h>int mkdir(const char *pathname, mode_t mode);0(成功)/-1(失败)
rmdir()删除空目录<unistd.h>int rmdir(const char *pathname);0(成功)/-1(失败)
1.2.2 C 语言标准库文件 IO 函数
库函数函数功能头文件参数模板返回值
fopen()打开文件流<stdio.h>FILE *fopen(const char *path, const char *mode);文件指针/NULL
freopen()重新打开文件流<stdio.h>FILE *freopen(const char *path, const char *mode, FILE *stream);文件指针/NULL
fclose()关闭文件流<stdio.h>int fclose(FILE *stream);0(成功)/EOF
fread()从文件流读取数据<stdio.h>size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);读取元素数
fwrite()向文件流写入数据<stdio.h>size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);写入元素数
fgetc()从文件流读取字符<stdio.h>int fgetc(FILE *stream);字符/EOF
getc()从文件流读取字符<stdio.h>int getc(FILE *stream);字符/EOF
getchar()从标准输入读取字符<stdio.h>int getchar(void);字符/EOF
fputc()向文件流写入字符<stdio.h>int fputc(int c, FILE *stream);字符/EOF
putc()向文件流写入字符<stdio.h>int putc(int c, FILE *stream);字符/EOF
putchar()向标准输出写入字符<stdio.h>int putchar(int c);字符/EOF
fgets()从文件流读取字符串<stdio.h>char *fgets(char *s, int size, FILE *stream);字符串指针/NULL
fputs()向文件流写入字符串<stdio.h>int fputs(const char *s, FILE *stream);非负数/EOF
fseek()移动文件流指针<stdio.h>int fseek(FILE *stream, long offset, int whence);0(成功)/-1
ftell()获取文件流当前位置<stdio.h>long ftell(FILE *stream);当前位置/-1
rewind()重置文件流到开头<stdio.h>void rewind(FILE *stream);无
fgetpos()获取文件流位置<stdio.h>int fgetpos(FILE *stream, fpos_t *pos);0(成功)/非 0
fsetpos()设置文件流位置<stdio.h>int fsetpos(FILE *stream, const fpos_t *pos);0(成功)/非 0
feof()检测文件结束标志<stdio.h>int feof(FILE *stream);非 0(结束)/0
ferror()检测文件错误标志<stdio.h>int ferror(FILE *stream);非 0(错误)/0
clearerr()清除错误和 EOF 标志<stdio.h>void clearerr(FILE *stream);无
fflush()刷新文件流缓冲区<stdio.h>int fflush(FILE *stream);0(成功)/EOF
setvbuf()设置文件流缓冲模式<stdio.h>int setvbuf(FILE *stream, char *buf, int mode, size_t size);0(成功)/非 0
setbuf()设置文件流缓冲区<stdio.h>void setbuf(FILE *stream, char *buf);无
fprintf()格式化输出到文件流<stdio.h>int fprintf(FILE *stream, const char *format, ...);输出字符数/负数
printf()格式化输出到标准输出<stdio.h>int printf(const char *format, ...);输出字符数/负数
sprintf()格式化输出到字符串<stdio.h>int sprintf(char *str, const char *format, ...);输出字符数/负数
fscanf()从文件流格式化输入<stdio.h>int fscanf(FILE *stream, const char *format, ...);匹配项数/EOF
scanf()从标准输入格式化输入<stdio.h>int scanf(const char *format, ...);匹配项数/EOF
sscanf()从字符串格式化输入<stdio.h>int sscanf(const char *str, const char *format, ...);匹配项数/EOF
tmpfile()创建临时文件<stdio.h>FILE *tmpfile(void);文件指针/NULL
tmpnam()生成临时文件名<stdio.h>char *tmpnam(char *s);文件名指针/NULL
remove()删除文件<stdio.h>int remove(const char *pathname);0(成功)/-1
rename()重命名文件<stdio.h>int rename(const char *oldpath, const char *newpath);0(成功)/-1
fileno()获取文件描述符<stdio.h>int fileno(FILE *stream);文件描述符/-1
fdopen()从文件描述符创建文件流<stdio.h>FILE *fdopen(int fd, const char *mode);文件指针/NULL

2. 文件 IO 部分代码演示

2.1 文件操作 1:打开文件方式

Makefile
myfile:myfile.c
	gcc -o $@ $^
.PHONY:clean
clean:	rm -f myfile
myfile.c
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>

int main(){
    umask(0);
    // 就近原则
    int fd = open("log.txt", O_CREAT | O_WRONLY | O_TRUNC, 0666);
    // OS 本身自带的系统调用,相当于 w
    if(fd < 0){
        perror("open");
        return 1;
    }
    const char* message = "ccc";
    write(fd, message, strlen(message));
    close(fd);
    return 0;
}

2.2 文件操作 2:重定向

Makefile
myfile:myfile.c
	gcc -o $@ $^
.PHONY:clean
clean:	rm -f myfile
myfile.c
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>

int main(){
    // 联系重定向
    // 格式化输出:上层的用户层,stdout -> 1
    //printf("hello printf\n"); // stdout -> 1
    //fprintf(stdout,"hello fprintf\n"); // stdout -> 1

    // 三个标准流,默认打开的
    //printf("stdin: %d\n",stdin->_fileno);
    //printf("stdout: %d\n",stdout->_fileno);
    //printf("stderr: %d\n",stderr->_fileno);

    FILE *fp = fopen("log.txt","w");
    //printf("log.txt: %d\n",fp->_fileno); // 3(fd 数组下标)
    fprintf(stdout,"hello stdout\n");
    close(1);

    int fda = open("loga.txt",O_CREAT | O_WRONLY | O_TRUNC,0666);
    int fdb = open("logb.txt",O_CREAT | O_WRONLY | O_TRUNC,0666);
    int fdc = open("logc.txt",O_CREAT | O_WRONLY | O_TRUNC,0666);
    fprintf(stdout,"fda : %d\n",fda);
    fprintf(stdout,"fdb : %d\n",fdb);
    fprintf(stdout,"fdc : %d\n",fdc);

    close(fda);
    close(fdb);
    close(fdc);
    return 0;
}
loga.txt
fda :1 fdb :4 fdc :5

2.3 文件操作 3:理解缓冲区

Print.c
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>

int main(){
    printf("hell world"); // 语言缓冲区 -> stdout->outbuffer
    sleep(40); // 测试杀死这个进程

    // C 库函数
    //printf("hello printf\n");
    //fprintf(stdout,"hello fprintf\n");
    //const char *msg1 = "hello fputs\n";
    //fputs(msg1,stdout);

    // 系统调用
    // const char *msg2 = "hello write\n";
    // write(1,msg2,strlen(msg2));
    //fork(); // 最后 return 0;
    return 0;
}

2.4 文件操作 4:实现 stdio

Makefile
testlibc:main.c my_stdio.c
	gcc -o $@ $^
.PHONY:clean
clean:	rm -f testlibc
main.c
#include"my_stdio.h"
#include<string.h>
#include<unistd.h>

int main(){
    My_FILE *fp = Myfopen("log.txt","a"); // 相当于把这个 log.txt 当显示器了
    if(!fp) // 打开文件失败或者底层 malloc 失败
        return 1;
    int cnt = 10;
    const char* msg = "hello world ";
    while(cnt--){
        Myfwrite(msg,1,strlen(msg),fp); // 模拟缓存的行为
        Myfflush(fp);
        sleep(2);
    }
    Myfclose(fp);
    return 0;
}
my_stdio.h
#pragma once

typedef struct{
    int fd;
    int flags;
    int mode; // 刷新策略
    char outbuffer[1024];
    int cap; // 缓冲区总容量
    int size; // 缓冲区当前的数据量
} My_FILE;

// 定义宏,是什么类型的缓冲
#define NONE_CACHE 1
#define LINE_CACHE 2
#define FULL_CACHE 4
// 1 2 4 只有一个比特位为 1(0001/0010/0100),检测起来比较容易

My_FILE *Myfopen(const char* pathname,const char* mode); // r w a 方式 --> 打开文件
int Myfwrite(const char* message,int size,int num,My_FILE *fp); // 写文件
void Myfflush(My_FILE *fp); // 刷新
void Myfclose(My_FILE *fp); // 关闭文件
my_stdio.c
#include"my_stdio.h"
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<stdlib.h> // malloc
#include<unistd.h>

static mode_t global_mode = 0666;

My_FILE *Myfopen(const char* pathname,const char* mode){ // r w a 方式 (在内部选择不同的模式)
    if(pathname == NULL || mode == NULL)
        return NULL;
    umask(0);
    int fd = 0;
    int flags = 0;
    if(strcmp(mode,"w")==0){
        flags = O_CREAT | O_WRONLY | O_TRUNC;
        fd = open(pathname,flags,global_mode);
    }
    if(strcmp(mode,"r")==0){
        flags = O_RDONLY;
        fd = open(pathname,flags);
    }
    if(strcmp(mode,"a")==0){
        flags = O_CREAT | O_WRONLY | O_APPEND;
        fd = open(pathname,flags,global_mode);
    }

    if(fd < 0) // 文件打开失败
        return NULL;

    // 创建 My_FILE 对象
    My_FILE* fp = (My_FILE*)malloc(sizeof(My_FILE));
    if(!fp) // 声明失败,直接返回
        return NULL;

    fp->fd = fd;
    fp->flags = flags;
    fp->mode = LINE_CACHE;
    fp->cap = 1024; // 容量,因为缓冲区大小定义的就是 1024,这一块也可以定义成宏
    fp->size = 0; // 当前缓冲区里没有数据,size 是 0
    memset(fp->outbuffer,0,sizeof(fp->outbuffer));
    return fp; // 至此上层拿到了这个被打开的文件
}

int Myfwrite(const char* message,int size,int num,My_FILE *fp){ // 一定程度上减少系统调用次数
    if(message == NULL || fp == NULL)
        return -1;

    int total = size * num;
    if(total + fp->size > fp->cap -1) // 保证不会越界 --> 总容量给\0 留个位置
        return -1;

    // 写入 --> 就相当于在进行数据拷贝 --> 核心 memcpy
    memcpy(fp->outbuffer + fp->size,message,total);
    fp->size += total;
    fp->outbuffer[fp->size]=0;

    if(fp->outbuffer[fp->size -1]=='\n' && (fp->mode & LINE_CACHE))
        Myfflush(fp); // 如果字符串结尾是\n,并且模式是 LINE(行缓冲),就直接强制刷新

    return num;
}

void Myfflush(My_FILE *fp){
    if(!fp)
        return;

    if(fp->size >0) // 强制刷新,只要有数据就刷新
    {
        // 系统调用
        // 所谓的刷新就是把数据从用户缓冲区拷贝到内核
        // 像从用户缓冲区拷贝到内核这种模式叫做 WB 模式
        // WB: Write Back(写回)
        write(fp->fd,fp->outbuffer,fp->size);
        fp->size = 0; // 清空

        // WT 模式,Write Though
        // 不仅仅要写入到内核缓冲区,还必须写到对应的硬件上
        fsync(fp->fd); // 强度做大一点
    }
}

void Myfclose(My_FILE *fp){ // 关闭文件
    if(!fp)
        return;
    Myfflush(fp); // 只要有数据,无脑刷新
    close(fp->fd); // 先刷新再关闭!先刷新,再关闭文件描述符!
}

目录

  1. Linux 文件操作:系统调用与标准库函数接口汇总及代码示例
  2. 1. 文件操作的系统调用和库函数各个接口
  3. 1.1 C 语言文件操作常用接口
  4. 1.2 系统调用和库函数汇总
  5. 1.2.1 系统调用
  6. 1.2.2 C 语言标准库文件 IO 函数
  7. 2. 文件 IO 部分代码演示
  8. 2.1 文件操作 1:打开文件方式
  9. Makefile
  10. myfile.c
  11. 2.2 文件操作 2:重定向
  12. Makefile
  13. myfile.c
  14. loga.txt
  15. 2.3 文件操作 3:理解缓冲区
  16. Print.c
  17. 2.4 文件操作 4:实现 stdio
  18. Makefile
  19. main.c
  20. my_stdio.h
  21. my_stdio.c
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Java IO 流与文件操作实战指南
  • 华为云 AI 算力部署:基于 Dify 集成 DeepSeek 构建实时翻译助手
  • WebAssembly 技术详解:概念、优势与开发流程
  • GitHub 教育认证通过后如何领取 Copilot Pro
  • Spring Boot 快速上手实战
  • 基于FPGA的五级积分梳状(CIC)滤波器Verilog实现
  • RetinaFace 与 CurricularFace 人脸识别实战
  • 基于 DeepSeek 的贪吃蛇游戏开发实战
  • 面试高频缓存算法:LRU 与 LFU 原理及 Java 实现
  • 图论算法基础:深入理解 DFS 与 BFS 遍历
  • LLaMA Factory 大模型微调全流程实战指南
  • AI 大模型行业应用面临的问题与挑战
  • PCL 点云处理算法与函数汇总
  • 大规模语言模型与智能代理:理论及实践应用
  • 基于 Spring Boot 的学生成绩管理系统设计与实现
  • C++ 拷贝构造函数与赋值运算符:深拷贝与浅拷贝辨析
  • AI 大模型驱动的软件开发全流程变革:从需求到运维
  • 基于指数预定义时间控制的固定翼无人机轨迹跟踪控制(Matlab 仿真)
  • 网络、运维与安全基础技术词汇汇总
  • AI 辅助开发:智能生成安装程序的新体验

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online