news 2026/7/5 20:31:10

一、Linux C编程笔记——文件IO(属于系统调用)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
一、Linux C编程笔记——文件IO(属于系统调用)

man 命令后面跟着两个参数的具体含义和用法:

数字1:Linux命令 数字2:系统调用 数字3:标准C库 如: man 1 ls man 2 open

1.open

一个进程内多次 open 打开同一个文件,在内存中并不会存在多份动态文件。

一个进程内多次 open 打开同一个文件,不同文件描述符所对应的读写位置偏移量是相互独立的。

加入了O_APPEND标志后,分别写已经变成了接续写。

int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); flags: ===这三个是文件访问权限标志,传入的 flags 参数中必须要包含其中一种标志,而且只能包含一种 O_RDONLY:RO O_WRONLY:WO O_RDWR:RW O_CREAT:文件不存在则创建,第 3 个参数只有在使用了 O_CREAT 或 O_TMPFILE 标志时才有效。 O_DIRECTORY:不是一个目录,则调用 open 失败 O_EXCL:一般结合 O_CREAT 标志一起使用,文件已经存在,则 open 函数返回错误。 O_NOFOLLOW:指向的是一个符号链接,将不对其进行解引用,直接返回错误。 O_TRUNC:将文件原本的内容全部丢弃 O_APPEND:write()函数对文件进行写文件,当前位置偏移量移动到文件末尾。 mode: 指定新建文件的访问权限。 当 flags 参数中包含 O_CREAT 或 O_TMPFILE 标志时才有效(O_TMPFILE 标志用于创建一个临时文件)

2.write

ssize_t write(int fd, const void *buf, size_t count); fd:文件描述符。 buf:指定写入数据对应的缓冲区。 count:指定写入的字节数

3.read

ssize_t read(int fd, void *buf, size_t count); fd:文件描述符。与 write 函数的 fd 参数意义相同。 buf:指定用于存储读取数据的缓冲区。 count:指定需要读取的字节数。 返回值:如果读取成功将返回读取到的字节数

4.close

int close(int fd); fd:文件描述符,需要关闭的文件所对应的文件描述符。 返回值:如果成功返回 0,如果失败则返回-1。

5.lseek(操作文件偏移量)

off_t lseek(int fd, off_t offset, int whence); fd:文件描述符。 offset:偏移量,以字节为单位。 whence: SEEK_SET:读写偏移量将指向 offset 字节位置处(从文件头部开始算); SEEK_CUR:读写偏移量将指向当前位置偏移量 + offset 字节位置处,offset 可以为正、也可以为 负,如果是正数表示往后偏移,如果是负数则表示往前偏移 SEEK_END:读写偏移量将指向文件末尾 + offset 字节位置处,同样 offset 可以为正、也可以为负, 如果是正数表示往后偏移、如果是负数则表示往前偏移。 返回值:成功将返回从文件头部开始算起的位置偏移量(字节为单位),也就是当前的读写位置;发生 错误将返回-1。

6._exit()和_Exit()(系统调用退出函数)

_exit()_Exit()两者等价,用来终止进程(这 2 个函数都是系统调用

7.exit()函数 (标准C库退出函数,执行清理再调用系统调用的退出函数)

exit()是一个标准 C 库函数,执行 exit()会执行一些清理工作,最后调用_exit()函数。exit()函数。

exit()会更加上层,封装了一些善后处理工作,最终都会调用系统调用_exit()_Exit()。

8.空洞文件

#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <string.h> #include <stdlib.h> int main(void) { int fd; int ret; char buffer[1024]; int i; /* 打开文件 */ fd = open("./hole_file", O_WRONLY|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); if (-1 == ret) { perror("lseek error"); goto err; } /* 将文件读写位置移动到偏移文件头 4096 个字节(4K)处 */ ret = lseek(fd, 4096, SEEK_SET); if (-1 == ret) { perror("lseek error"); goto err; } /* 初始化 buffer 为 0xFF */ memset(buffer, 0xFF, sizeof(buffer)); /* 循环写入 4 次,每次写入 1K */ for (i = 0; i < 4; i++) { ret = write(fd, buffer, sizeof(buffer)); if (-1 == ret) { perror("write error"); goto err; } } ret = 0; err: /* 关闭文件 */ close(fd); exit(ret); }

lseek允许文件偏移量超出文件长度,譬如有一个 test_file,该文件的大小是 4K(也就是 4096 个字节),如果通过 lseek 系统调用将该文件的读写偏移量移动到偏移文件头部 6000 个字节处,接下来使用write会从6000字节开始写,4096~6000 字节之间出现了一个空洞,这部分区域就被称为文件空洞,那么相应的该文件也被称为空洞文件。文件空洞部分实际上并不会占用任何物理空间。

9.dup(复制文件描述符由系统分配,可以实现接续写)

int dup(int oldfd); oldfd:需要被复制的文件描述符。 返回值:成功时将返回一个新的文件描述符,由操作系统分配,失败将返回-1,并设置errno值 /* 复制文件描述符 */ fd2 = dup(fd1); if (-1 == fd2) { perror("dup error"); ret = -1; goto err1; }

10.dup2 (指定一个文件描述符)

int dup2(int oldfd, int newfd); oldfd:需要被复制的文件描述符。 newfd:指定一个文件描述符(需要指定一个当前进程没有使用到的文件描述符)。 返回值:成功时将返回一个新的文件描述符,失败将返回-1,并且会设置 errno 值 /* 复制文件描述符 */ fd2 = dup2(fd1, 100); if (-1 == fd2) { perror("dup error"); ret = -1; goto err1; }

11.原子操作

(1)O_APPEND 实现原子操作

先定位到文件末尾,然后写,防止覆盖。

(2)pread()和 pwrite()

pread()和 pwrite()都是系统调用,与read()、write()函数的作用一样

区别在于, pread()和 pwrite()可用于实现原子操作

ssize_t pread(int fd, void *buf, size_t count, off_t offset); ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset); pread 相当于调用 lseek 后再调用 read pwrite 相当于调用 lseek 后再调用 writ

(3)O_EXCL

将“判断文件是否存在、创建文件”这两个步骤合成为一个原子操作

12.fcntl

可通过"man 2 fcntl"命令查看

int fcntl(int fd, int cmd, ... /* arg */ ) fd:文件描述符。 cmd:操作命令。 ⚫ 复制文件描述符(cmd=F_DUPFD 或 cmd=F_DUPFD_CLOEXEC); ⚫ 获取/设置文件描述符标志(cmd=F_GETFD 或 cmd=F_SETFD); ⚫ 获取/设置文件状态标志(cmd=F_GETFL 或 cmd=F_SETFL); ⚫ 获取/设置异步 IO 所有权(cmd=F_GETOWN 或 cmd=F_SETOWN); ⚫ 获取/设置记录锁(cmd=F_GETLK 或 cmd=F_SETLK); …:fcntl 函数是一个可变参函数,第三个参数需要根据不同的 cmd 来传入对应的实参,配合 cmd 来使 用。

13.ioctl 函数

int ioctl(int fd, unsigned long request, ...); fd:文件描述符。 request:此参数与具体要操作的对象有关,没有统一值,表示向文件描述符请求相应的操作; ...:此函数是一个可变参函数,根据 request 参数来决定,配合 request 来使用。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/3 14:23:14

科技局如何精准识别辖区内企业创新能力差异以实现资源高效配置?

观点作者&#xff1a;科易网-国家科技成果转化&#xff08;厦门&#xff09;示范基地 核心要点 科技局需以数智化工具精准识别企业创新能力差异&#xff0c;实现资源高效配置&#xff0c;从经验判断转向数据决策。科易网等机构通过科创知识图谱、数智工具平台&#xff0c;解决产…

作者头像 李华
网站建设 2026/7/3 6:11:02

2026 中国大模型 API 价格战全景图:谁在涨,谁在降

如果你在 2025 年初调用一次 GPT-4 级别模型要花 15 美元&#xff0c;到了 2026 年中&#xff0c;用国产最强模型跑同样的任务可能只要 3 毛钱。这不是夸张&#xff0c;是正在发生的现实。 过去 18 个月&#xff0c;中国大模型 API 市场经历了一场堪称互联网史上最猛烈的价格重…

作者头像 李华
网站建设 2026/7/3 17:27:20

WaveTools鸣潮工具箱:如何一键解锁120FPS高帧率游戏体验

WaveTools鸣潮工具箱&#xff1a;如何一键解锁120FPS高帧率游戏体验 【免费下载链接】WaveTools &#x1f9f0;鸣潮工具箱 项目地址: https://gitcode.com/gh_mirrors/wa/WaveTools 你是否在为《鸣潮》游戏的60FPS帧率限制感到困扰&#xff1f;即使拥有高性能显卡&#…

作者头像 李华
网站建设 2026/7/3 21:39:04

请完善语法及使用示例,我需要全部语法及其对应的示例

TimescaleDB 核心语法与使用示例全集 1. 超表 (Hypertable) 管理 1.1 创建超表 -- 基础创建&#xff1a;将普通表转换为超表 CREATE TABLE conditions (time TIMESTAMPTZ NOT NULL,location TEXT NOT NULL,temperature DOUBLE PRECISION ); SELECT create_hypertable(condit…

作者头像 李华
网站建设 2026/7/2 23:05:18

实测对比:DECIMER、Img2Mol、MolScribe,哪个化学结构识别工具更靠谱?

化学结构识别工具横评&#xff1a;DECIMER、Img2Mol与MolScribe实战对比在药物研发和化学信息学领域&#xff0c;将分子结构图像转换为机器可读的SMILES字符串是一项基础而关键的任务。面对DECIMER、Img2Mol和MolScribe这三款主流开源工具&#xff0c;科研人员常常陷入选择困境…

作者头像 李华