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

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 可监听写就绪。

相关文章:

  • ubuntu--安装双系统
  • 规则引擎 - Easy Rules
  • Spark和Hadoop的区别和联系
  • 【AI提示词】数据分析专家
  • 系统安全及应用
  • 一个关于相对速度的假想的故事-3
  • Linux 入门十一:Linux 网络编程
  • PyCharm 在 Linux 上的完整安装与使用指南
  • arxml文件中的schema是什么?有什么作用?
  • Kafka 在小流量和大流量场景下的顺序消费问题
  • typedef MVS_API CLISTDEF0IDX(ViewScore, IIndex) ViewScoreArr;
  • Vue3 源码解析(六):响应式原理与 reactive
  • DePIN驱动的分布式AI资源网络
  • Python 爬虫如何获取淘宝商品的 SKU 详细信息
  • 云服务器怎么选择防御最合适
  • 深度学习中的归一化技术:从原理到实战全解析
  • 使用 Logstash 迁移 MongoDB 数据到 Easysearch
  • C语言中联合体(Union)和结构体(Struct)的嵌套用法
  • Unity打开项目时目标平台被改变
  • 新能源汽车充电桩运营模式的发展与优化路径探析
  • 南部战区海军新闻发言人发表谈话
  • 数智时代出版专业技能人才培养研讨会在沪举行
  • 从高铁到住房:“富足议程”能否拯救美国的进步主义?
  • 美国国务卿:乌克兰问题谈判不能一直停滞不前
  • 上海自然博物馆下月开启中国恐龙大展,还在筹备中国古人类大展
  • “80后”张汉强已任浙江丽水市委常委、市纪委书记