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

ubuntu学习day4

4 Linux 文件操作

4.1 基于文件指针的文件操作

  • Linux 中对目录和设备的操作都是文件操作,文件分为普通文件,目录文件,链接文件和设备文件。
  • 普通文件:也称磁盘文件,并且能够进行随机的数据存储(能够自由 seek 定位到某一个位置)。
  • 管道:是一个从一端发送数据,另一端接收数据的数据通道。
  • 目录:也称为目录文件,它包含了保存在目录中文件列表的简单文件。
  • 设备:该类型的文件提供了大多数物理设备的接口。它又分为两种类型:字符型设备和块设备。字符型设备一次只能读出和写入一个字节的数据,包括调制解调器、终端、打印机、声卡以及鼠标;块设备必须以一定大小的块来读出或者写入数据,块设备包括 CD-ROM、RAM 驱动器和磁盘驱动器等。一般而言,字符设备用于传输数据,块设备用于存储数据
  • 链接:类似于 Windows 的快捷方式,指包含到达另一个文件路径的文件。
  • 基于文件指针的文件操作函数是 ANSI 标准函数库的一部分。

4.1.2 文件的创建,打开与关闭

使用文件指针来访问文件的方法是由标准 C 规定的,相关函数的原型为:

#include <stdio.h> //头文件包含
FILE* fopen(const char* path, const char* mode);//文件名 模式
int fclose(FILE* stream)
  • fopen 以 mode 的方式打开或创建文件,如果成功,将返回一个文件指针,失败则返回 NULL。fopen 创建的文件的访问权限将以 0666 与当前的 umask 结合来确定。

  • mode 的可选模式列表,如下所示:
    在这里插入图片描述

  • 在 Linux 系统中,mode 里面的’b’(二进制)可以去掉,但是为了保持与其他系统的兼容性,建议不要去掉。

  • ab 和 ab+为追加模式,在此两种模式下,在一开始的时候读取文件内容是从文件起始处开始读取的,而无论文件读写点定位到何处,在写数据时都将是在文件末尾添加(写完以后读写点就移动到文件末尾了),所以比较适合于多进程写同一个文件的情况下保证数据的完整性。

4.1.3 读写文件

基于文件指针的数据读写函数较多,可分为如下几组:

块读写
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
  • freadstream 读取 nmemb 个元素到 ptr,每元素 size 字节。
  • fwriteptr 写入 nmemb 个元素到 stream,每元素 size 字节。
  • 操作从当前读写点开始,完成后自动移动 size * nmemb 字节。
格式化读写
#include <stdio.h>
int printf(const char *format, ...);
int scanf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sprintf(char *str, const char *format, ...);
int sscanf(const char *str, const char *format, ...);
  • fprintf 写入 streamsprintf 写入字符串;fscanf, sscanf 对应读取。
单字符读写
#include <stdio.h>
int fgetc(FILE *stream);
int fputc(int c, FILE *stream);
int getc(FILE *stream);
int putc(int c, FILE *stream);
int getchar(void);
int putchar(int c);
  • getchar, putchar 对应 stdin/stdout
字符串读写
char *fgets(char *s, int size, FILE *stream);
int fputs(const char *s, FILE *stream);
int puts(const char *s);
char *gets(char *s);
  • fgetsstream 读取一行,保留 \nfputs 写一行,不自动加 \n
  • gets 不安全,建议使用 fgets
文件定位
#include <stdio.h>
int feof(FILE *stream);
int fseek(FILE *stream, long offset, int whence);
long ftell(FILE *stream);
void rewind(FILE *stream);
  • fseek(stream, offset, whence) 定位:SEEK_SET, SEEK_CUR, SEEK_END
  • ftell 返回当前偏移;rewind 移至开头;feof 判断 EOF。

4.1.4 文件的权限

#include <sys/stat.h>
int chmod(const char* path, mode_t mode);
  • mode0777(八进制),修改文件访问权限。

4.2 目录操作

4.2.1 获取、改变当前目录

#include <unistd.h>
char *getcwd(char *buf, size_t size);
int chdir(const char *path);
  • getcwd(NULL,0) 自动 malloc 空间,需 free
  • chdir(path) 等同 cd 命令。

4.2.2 创建和删除目录

#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int mkdir(const char *pathname, mode_t mode);
int rmdir(const char *pathname);
  • mkdir 创建目录,mode 权限;rmdir 删除空目录。
  • 环境变量:echo $PATH; export PATH=$PATH:dir

4.2.3 目录的存储原理

  • 文件系统用 inode 管理文件:存放位置信息、类型、权限、时间等。
  • 目录文件固定大小,存放多个 dirent 节点(链式结构)。
struct dirent {ino_t d_ino;off_t d_off;unsigned short d_reclen;unsigned char d_type;char d_name[256];
};

4.2.4 目录相关操作

#include <dirent.h>
DIR *opendir(const char *name);
struct dirent *readdir(DIR *dir);
void rewinddir(DIR *dir);
void seekdir(DIR *dir, off_t offset);
off_t telldir(DIR *dir);
int closedir(DIR *dir);
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *pathname, struct stat *buf);
  • 打开目录后,用 readdir 迭代,最后 closedir
  • stat 获取文件状态。

4.3 基于文件描述符的文件操作

4.3.1 文件描述符

  • POSIX 提供无缓冲 I/O,文件由整数描述符表示。文件描述符索引内核中文件表。

4.3.2 打开、创建和关闭文件

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);
int close(int fd);
  • open 返回 fd,失败返回 -1
  • 常用 flags:O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_EXCL, O_TRUNC, O_APPEND, O_NONBLOCK, O_SYNC
  • creat(path, mode) 等价 open(path, O_CREAT|O_TRUNC|O_WRONLY, mode)
  • close(fd) 释放锁并递减引用计数。

4.3.3 读写文件

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
  • 失败返回 -1,读完返回 0,否则返回字节数。

4.3.4 改变文件大小

#include <unistd.h>
int ftruncate(int fd, off_t length);
  • 将文件截断或扩展到 length,成功返回 0
  • 常与 mmap 配合使用。

4.3.5 文件映射

#include <sys/mman.h>
void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off);
  • 将文件映射到内存,无需 read/write
  • 需与 ftruncate 配合调整文件大小。

4.3.6 文件定位

#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
  • lseek 返回新的偏移位置,可创建文件空洞。

4.3.7 获取文件信息

#include <sys/stat.h>
#include <unistd.h>
int stat(const char *file_name, struct stat *buf);
int fstat(int fd, struct stat *buf);
  • struct stat 包含多种属性:st_mode, st_size, st_atime, st_mtime, st_ctime 等。
  • 宏判断类型:S_ISREG, S_ISDIR, S_ISLNK, etc。

4.3.8 文件描述符的复制

#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);
  • dup 自动分配新描述符;dup2 指定新描述符,新描述符若已打开则先关闭。
  • 应用:输出重定向。

4.3.9 文件描述符和文件指针

  • fopen 本质调用 open,可用 fileno(fp) 获取底层 fd
  • fdopen(fd, mode)fd 创建缓冲流。

4.3.10 标准输入输出文件描述符

  • STDIN_FILENO=0, STDOUT_FILENO=1, STDERR_FILENO=2 对应 stdin, stdout, stderr

4.3.11 管道

  • 无名管道:半双工通信,文件类型 p

  • Shell:

    mkfifo name
    cat name   # 读
    echo "..." > name   # 写
    
  • C 程序分别 open(..., O_RDONLY) / O_WRONLY

4.4 I/O 多路转接模型

4.4.1 读取阻塞

  • 默认阻塞模式,read 无数据则阻塞。
  • 双管道可实现全双工。

4.4.2 select

#include <sys/select.h>
#include <sys/time.h>
int select(int maxfd, fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout);
  • FD_ZERO, FD_SET, FD_CLR, FD_ISSET 操作 fd_set
  • timeout NULL 永久等待。

4.4.3 select 的退出机制

  • 写端关闭后,读端 read 返回 0select 标记可读。
  • 应检测 read 返回 0 并退出。

4.4.4 超时处理

  • 每次调用前需重置 struct timeval

4.4.5 写集合

  • 写阻塞:管道满时写端阻塞;select 可监听写就绪。
http://www.xdnf.cn/news/939.html

相关文章:

  • SaltStack远程协助工具
  • Oracle for Linux安装和配置(11)——Linux配置
  • Franka机器人ROS 2来袭:解锁机器人多元应用新可能
  • SpringBoot + Vue 实现云端图片上传与回显(基于OSS等云存储)
  • 单片机可以用来做机器人吗?
  • 超详细实现单链表的基础增删改查——基于C语言实现
  • 聚类算法(K-means、DBSCAN)
  • 基于DeepSeek/AI的资产测绘与威胁图谱构建
  • Java高频面试之并发编程-04
  • LangGraph(一)——QuickStart样例中的第一步
  • linux sysfs的使用
  • XAttention
  • 初识Redis · C++客户端list和hash
  • 爬楼梯(每日一题-简单)
  • 240422 leetcode exercises
  • 13 数据存储单位与 C 语言整数类型:从位到艾字节、常见整数类型及其范围、字面量后缀、精确宽度类型详解
  • Kotlin基础(①)
  • 条件变量底层实现原理
  • 2025 年职业院校技能大赛网络建设与运维赛项Docker赛题解析
  • Spark SQL概述(专业解释+生活化比喻)
  • Redis专题
  • NLP高频面试题(四十九)大模型RAG常见面试题解析
  • 基于大模型的血栓性外痔全流程风险预测与治疗管理研究报告
  • 检测IP地址欺诈风险“Scamalytics”
  • M2N2 解读
  • 卷积神经网络--手写数字识别
  • Spark-SQL(四)
  • 微服务架构下数据库范式的失效与反范式设计的崛起
  • 将长循环任务拆分成多个小步骤,以非阻塞的方式执行,在裸机环境下的实现方法
  • 【第16届蓝桥杯C++C组】--- 2025