Linux编程:1、文件编程
一、Linux 文件编程与 C 语言文件编程的区别
特性 | C 语言 I/O 库函数 | Linux 文件编程(系统调用) |
---|---|---|
实现层面 | 用户空间(glibc 库) | 内核空间(系统调用) |
跨平台性 | 跨平台(Windows/Linux) | 仅限 Linux 系统 |
性能 | 带用户空间缓冲区,默认高效 | 需手动管理缓冲区,使用得当更快 |
底层依赖 | 依赖系统调用(如 Linux 的 open) | 直接操作内核 API |
核心差异:
- C 语言函数是系统调用的封装,例如
fopen
底层调用open
。 - 系统调用适合底层控制(如文件锁、内存映射),库函数适合通用文件操作。
二、文件描述符(File Descriptor, FD)
1. 基本概念
- 作用:Linux 中对文件(含设备)的唯一标识,通过整数(FD)操作文件。
- 进程关联:每个进程维护独立的 FD 表,记录打开的文件。
2. 预定义描述符
FD | 宏定义 | 用途 |
---|---|---|
0 | STDIN_FILENO | 标准输入 |
1 | STDOUT_FILENO | 标准输出 |
2 | STDERR_FILENO | 标准错误输出 |
3. 范围与限制
- 默认范围:0 ~
OPEN_MAX-1
。 - 查看系统限制:
cat /proc/sys/fs/file-max
。 - 修改限制(需 root):
echo 2048 > /proc/sys/fs/file-max
。
4. 用法示例
- Shell 脚本中使用 FD:
FILE *fp = fopen("data.txt", "r"); int fd = fileno(fp); // 转换为文件描述符
三、文件操作基础
1. 打开文件(open
)
- 函数原型:
int open(const char *pathname, int flags); // 无权限模式 int open(const char *pathname, int flags, mode_t mode); // 带权限模式
- 头文件:
#include <fcntl.h>
,#include <sys/stat.h>
。 - 关键参数:
flags
:必选其一(O_RDONLY
/O_WRONLY
/O_RDWR
),可组合其他标志:O_CREAT
:文件不存在时创建。O_EXCL
:与O_CREAT
联用,若文件存在则打开失败。O_APPEND
:写入时追加到文件末尾。
mode
:新文件权限(如0644
表示 rw-r--r--),需与O_CREAT
配合使用。
- 返回值:成功返回 FD(非负整数),失败返回 - 1。
示例:创建并读写文件
int fd = open("data.txt", O_RDWR | O_CREAT, 0600); // 0600表示所有者可读写
if (fd < 0) { perror("open failed"); }
2. 创建文件(creat
)
- 等价于:
open(pathname, O_WRONLY | O_CREAT | O_TRUNC, mode)
。 - 函数原型:
int creat(const char *pathname, mode_t mode);
。
3. 关闭文件(close
)
- 函数原型:
int close(int fd);
。 - 注意:不关闭可能导致 FD 耗尽,影响后续打开文件。
四、读写文件
1. 读文件(read
)
- 函数原型:
ssize_t read(int fd, void *buf, size_t count);
- 返回值:
- 成功:实际读取字节数(可能小于
count
,如文件末尾)。 - 失败:-1,设置
errno
。
- 成功:实际读取字节数(可能小于
- 性能优化:避免频繁小尺寸读取,利用页缓存(4KB 为单位)。
2. 写文件(write
)
- 函数原型:
ssize_t write(int fd, const void *buf, size_t count);
- 返回值:成功返回实际写入字节数,失败返回 - 1。
- 示例:追加写入
int fd = open("data.txt", O_WRONLY | O_APPEND); write(fd, "Hello World!", 12);
3. C 语言与系统调用性能对比
- 场景:写入 100 万次数据。
- C 语言(
fwrite
):用户空间缓冲区优化,耗时约 0.02 秒。#include <stdio.h> #include <stdlib.h>#define MAX 1000000int main(void) {FILE* fp = fopen("data1", "wb");if (fp == NULL) {perror("fopen failed.");exit(1);}for (int i = 0; i < MAX; i++) {fwrite(&i, sizeof(int), 1, fp);}fclose(fp);return 0; }
- 系统调用(
write
):无用户缓冲区,耗时约 0.18 秒,需手动添加缓冲区优化。#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h>#define MAX 1000000int main(void) {int fd = open("data2", O_RDWR | O_CREAT | O_TRUNC, 0666);if (fd == -1) {perror("open file failed.");exit(1);}for (int i = 0; i < MAX; i++) {write(fd, &i, sizeof(int));}close(fd);return 0; }
- 原因:
系统函数在用户层没有缓冲区,在内核层有缓冲区,但是缓冲区很小。所以大量数据在写入文件时,频繁刷新缓冲区降低了写入速率。(缓冲区满了才真正写入) 所以系统函数(如 write)需要加自定义缓冲区以提高速率, 而标准 C 函数(如 fwrite)在用户层有默认的缓冲区,所以案例一比案例二更快
- C 语言(
- 改进系统调用的代码:
#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h>#define MAX 1000000 #define BUFF_SIZE 512int main(void) {int fd = open("data2", O_RDWR | O_CREAT | O_TRUNC, 0666);if (fd == -1) {perror("open file failed.");exit(1);}int buffer[BUFF_SIZE];for (int i = 0; i < MAX; i++) {buffer[i % BUFF_SIZE] = i;if ((i + 1) % BUFF_SIZE == 0) {write(fd, buffer, sizeof(buffer));}}close(fd);return 0; }
结论:在使用系统函数接口时,如果自定义了一个合适的缓冲区,会使速度显著提升
五、文件偏移量与定位(lseek
)
- 作用:调整文件读写位置(字节偏移量)。
- 函数原型:
off_t lseek(int fd, off_t offset, int whence);
whence
参数:SEEK_SET
:从文件开头偏移offset
。SEEK_CUR
:从当前位置偏移offset
(可正可负)。SEEK_END
:从文件末尾偏移offset
(通常为负数)。
- 示例:修改文件指定位置内容
int fd = open("test.txt", O_RDWR); lseek(fd, 5, SEEK_SET); // 定位到第6字节(索引从0开始) write(fd, "ABC", 3); // 覆盖写入
六、文件状态与元数据(stat
系列函数)
- 作用:获取文件类型、权限、大小、时间戳等信息。
- 相关函数:
函数 参数 说明 stat
路径名 获取文件或符号链接指向的文件信息 lstat
路径名 获取符号链接本身的信息 fstat
文件描述符 通过 FD 获取文件信息 - 关键结构体:
struct stat {mode_t st_mode; // 文件类型(如`S_ISDIR`判断目录)off_t st_size; // 文件大小(字节)ino_t st_ino; // inode节点号(唯一标识)time_t st_mtime; // 最后修改时间 };
示例:判断文件类型
struct stat status;
stat("test.txt", &status);
if (S_ISREG(status.st_mode)) { printf("普通文件\n"); }
七、硬链接与软链接
1. 硬链接(Hard Link)
- 本质:多个文件名指向同一 inode,共享物理数据。
- 特点:
- 不能跨文件系统,不能链接目录。
- 删除任意硬链接不影响其他链接,仅当所有硬链接删除后文件才被删除。
- 创建命令:
ln <源文件> <链接名>
。
2. 软链接(符号链接,Symbolic Link)
- 本质:独立文件,存储目标文件路径。
- 特点:
- 可跨文件系统,可链接目录。
- 源文件删除后成为 “死链接”,访问时报错。
- 创建命令:
ln -s <源文件或目录> <链接名>
。
3. 对比表格
特性 | 硬链接 | 软链接 |
---|---|---|
文件类型 | 与源文件相同(普通文件) | 特殊文件(类型为l ) |
跨文件系统 | 不支持 | 支持 |
源文件删除影响 | 无(仅硬链接数减 1) | 失效(死链接) |
存储空间 | 共享 inode,不占用额外空间 | 存储路径,占用少量空间 |
八、文件锁机制
1. 作用
避免多进程并发访问文件导致的数据竞争,分为建议性锁和强制性锁。
2. 核心函数(fcntl
)
#include <unistd.h>
#include <fcntl.h>
#include <sys/file.h>int fcntl(int fd, int cmd, struct flock *lock);
cmd
参数:F_SETLK
:设置锁(非阻塞,失败直接返回)。F_GETLK
:查询锁状态。
struct flock
结构体:struct flock {short l_type; // 锁类型(F_RDLCK读锁/F_WRLCK写锁/F_UNLCK解锁)off_t l_start; // 偏移量(配合l_whence)off_t l_len; // 加锁长度(0表示到文件末尾) };
3. 建议性锁(默认)
- 特点:不强制阻止访问,需进程主动检查锁状态。
- 示例:检测写锁
struct flock lock = {.l_type = F_WRLCK, .l_whence = SEEK_SET}; fcntl(fd, F_GETLK, &lock); if (lock.l_pid != -1) { printf("文件被进程%d锁定\n", lock.l_pid); }
4. 强制性锁
- 启用条件:
- 挂载文件系统时添加
mand
选项:sudo mount -o remount,mand /
。 - 设置文件权限为
g+s
且取消组执行权限:chmod g+s,g-x test.txt
。
- 挂载文件系统时添加
- 特点:不兼容的操作会被阻塞(如读锁存在时写操作阻塞)。
九、内存映射(mmap
)
1. 作用
将文件数据映射到进程地址空间,直接通过指针操作文件,减少内核与用户空间的数据拷贝。
2. 核心函数
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *addr, size_t length); // 解除映射
- 关键参数:
prot
:权限(如PROT_READ | PROT_WRITE
)。flags
:MAP_SHARED
:修改会写回文件,可被其他进程共享。MAP_PRIVATE
:修改仅在当前进程可见,不影响原文件。
offset
:必须为 4KB(4096 字节)的整数倍。
3. 优势与场景
- 优势:
- 减少
read/write
系统调用的拷贝开销(仅 1 次拷贝)。 - 简化随机访问(直接操作指针)。
- 减少
- 适用场景:
- 大文件随机读写。
- 多进程共享文件数据(通过
MAP_SHARED
)。
- 缺点:
- 不适合频繁写操作或变长文件。
4. 示例:读取文件内容
int fd = open("test.txt", O_RDONLY);
off_t len = lseek(fd, 0, SEEK_END);
char *buf = (char*)mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
printf("%s", buf); // 直接打印映射内容
munmap(buf, len);
十、关键快捷键与命令
man
命令:查看帮助文档man 2 open
:查看系统调用open
的手册。man -f open
:查看open
所属章节。
man
快捷键:Space
:下翻一页;b
:上翻一页;/字符串
:搜索。
相关文章:

Linux编程:1、文件编程
一、Linux 文件编程与 C 语言文件编程的区别 特性C 语言 I/O 库函数Linux 文件编程(系统调用)实现层面用户空间(glibc 库)内核空间(系统调用)跨平台性跨平台(Windows/Linux)仅限 Li…...

Kyosan K5BMC ELECTRONIC INTERLOCKING MANUAL 电子联锁
Kyosan K5BMC ELECTRONIC INTERLOCKING MANUAL 电子联锁...

【Spark征服之路-2.3-Spark运行架构】
运行架构 Spark 框架的核心是一个计算引擎,整体来说,它采用了标准 master-slave 的结构。 如下图所示,它展示了一个 Spark 执行时的基本结构。图形中的 Driver 表示 master,负责管理整个集群中的作业任务调度。图形中的 Executor …...
PART 6 树莓派小车+QT (TCP控制)
1. 树莓派作为服务器的程序 (1)服务器tcp_server_socket程序 可以实现小车前进、后退、左转、右转、加减速(可能不行) carMoveControl.py import RPi.GPIO as GPIO import time import tty,sys,select,termios import socket…...
软珊瑚成分 CI-A:靶向口腔癌细胞的 “氧化利剑” 与 ERK 密码
在生命科学探索的浩瀚星海中,癌症研究始终是最为耀眼却又充满挑战的领域之一。口腔癌,作为全球范围内日益严峻的公共健康问题,尤其在中南亚、美拉尼西亚以及我国台湾地区,其发病率和死亡率持续攀升,如同隐藏在黑暗中的…...

Cilium动手实验室: 精通之旅---4.Cilium Gateway API - Lab
Cilium动手实验室: 精通之旅---4.Cilium Gateway API - Lab 1. 环境准备2. API 网关--HTTP2.1 部署应用2.2 部署网关2.3 HTTP路径匹配2.4 HTTP头匹配 3. API网关--HTTPS3.1 创建TLS证书和私钥3.2 部署HTTPS网关3.3 HTTPS请求测试 4. API网关--TLS 路由4.1 部署应用4.2 部署网关…...
【芯片设计- RTL 数字逻辑设计入门 4.2 -- 组合逻辑赋值 + 时序逻辑状态保持】
文章目录 Overview原语句分析变量含义假设(根据命名推测)状态更新逻辑详解状态转移逻辑举个实际例子小结Overview 本文将详细介绍 verilog rtl 中 assign reg_halt_mode_nx = halt_taken | (reg_halt_mode & ~halt_return);的作用,以及这里为何要使用 reg_halt_mode,…...
如何使用索引和条件批量更改Series数据
视频演示 如何通过索引与布尔条件修改 pandas Series?实操演示来了 一、前言:掌握Series数据修改是数据处理的基础 在使用Python进行数据分析时,Pandas库的Series对象是最常用的结构之一。在上一个视频中我们已经学习了如何创建Series对象&a…...

Java转Go日记(六十):gin其他常用知识
1. 日志文件 package mainimport ("io""os""github.com/gin-gonic/gin" )func main() {gin.DisableConsoleColor()// Logging to a file.f, _ : os.Create("gin.log")gin.DefaultWriter io.MultiWriter(f)// 如果需要同时将日志写入…...

89.实现添加收藏的功能的后端实现
实现完查看收藏列表之后,实现的是添加收藏的功能 我的设想是:在对话界面中,如果用户认为AI的回答非常好,可以通过点击该回答对应的气泡中的图标,对该内容进行添加 所以后端实现为: service类中添加&…...

v1.0.1版本更新·2025年5月22日发布-优雅草星云物联网AI智控系统
v1.0.1版本更新2025年5月22日发布-优雅草星云物联网AI智控系统 开源地址 星云智控官网: 优雅草星云物联网AI智控软件-移动端vue: 优雅草星云物联网AI智控软件-移动端vue 星云智控PC端开源: 优雅草星云物联网AI智控软件-PC端vue: 优雅草星云物联网AI…...

如何创造出一种不同于程序语言的人与机器自然交互语言?
人机交互自然语言通过模拟人类日常交流方式,使机器能够理解并响应人类的自然表达,从而打破编程语言的复杂性壁垒,极大地提升人机协同的效率和自然性,让机器更好地融入人类的工作与生活场景。创造一种通用的人与机器自然交互语言是…...

宝塔think PHP8 安装使用FFmpeg 视频上传
宝塔think PHP8 安装使用FFmpeg 一、 安装think PHP8二、安装 FFmpeg1,登录到宝塔面板。2,进入“软件商店”。3,搜索“FFmpeg”。4,选择版本点击安装。5,检查 FFmpeg 是否安装成功6, 在 ThinkPHP 8 中使用 …...

26.【新型数据架构】-零ETL架构
26.【新型数据架构】-零ETL架构:减少数据移动,原系统直接分析;典型实现(AWS Zero-ETL) 一、零ETL的本质:从“数据搬运工”到“数据翻译官” 传统ETL(Extract-Transform-Load)需要将数据从源系统抽取、清洗、转换后加载到目标系统,这一过程往往耗时费力,且面临数据延…...

静态相机中的 CCD和CMOS的区别
文章目录 CCD处理方式CMOS处理方式两者区别 首先根据 成像原理,CCD和CMOS的作用是一致的,都是为了将光子转化为数字图像,只是 转换的方式出现差异。 CCD处理方式 获取光子: 在电荷耦合器件(CCD)传感器中…...
【MySQL基础】数据库的备份与还原
MySQL学习: https://blog.csdn.net/2301_80220607/category_12971838.html?spm1001.2014.3001.5482 前言: 在数据库管理中,删除操作是不可逆的,因此备份是数据安全的重要保障。下面我将详细介绍MySQL数据库删除前的备份方法&am…...

bug:undefined is not iterable (cannot read property Symbol(Symbol.iterator))
1.如图 2.分析 关键报错提示: undefined is not iterable (cannot read property Symbol(Symbol.iterator)) 直译: undefined是不可迭代的(不能读取属性Symbol(Symbol.iterator)) 理解: 有一个值、不存在&#x…...
为UE5的Actor添加能够读写姿态的功能
提问 // Copyright 2019-2022 The MathWorks, Inc. #include "SetGetActorLocation.h"// Sets default values ASetGetActorLocation::ASetGetActorLocation():SignalReader(nullptr), SignalWriter(nullptr) { }void ASetGetActorLocation::Sim3dSetup() { Super::…...

机器学习:支持向量机(SVM)原理解析及垃圾邮件过滤实战
一、什么是支持向量机(SVM) 1. 基本概念 1.1 二分类问题的本质 在机器学习中,分类问题是最常见的任务之一。最简单的情况就是二分类:比如一封邮件是“垃圾邮件”还是“正常邮件”?一个病人是“患病”还是“健康”&a…...

LLM Agent 如何颠覆股价预测的传统范式
写在前面 股价预测,金融领域的“圣杯”之一,吸引了无数研究者和投资者。传统方法从技术指标到复杂的计量经济模型,再到机器学习,不断演进,但市场的高度复杂性、非线性和充斥噪声的特性,使得精准预测依然是巨大的挑战。大型语言模型(LLM)的崛起,特别是LLM Agent这一新…...
App/uni-app 离线本地存储方案有哪些?最推荐的是哪种方案?
以下是 UniApp 离线本地存储方案的详细介绍及推荐方案分析: 一、UniApp 离线本地存储方案分类 1. 基于 uni.storage 系列 API(跨端基础方案) API 及特点: 提供 uni.setStorage(异步存储)、uni.getStorag…...

【案例分享】如何借助JS UI组件库DHTMLX Suite构建高效物联网IIoT平台
随着工业领域数字化进程的持续加快,Web 技术在实现实时监控、数据可视化与控制系统等方面正扮演着越来越核心的角色。来自智利的科技企业 Wise Data Global 就是这一趋势中的积极践行者。他们借助慧都科技代理的 DHTMLX Suite JavaScript UI 控件库,为遥…...

Skia如何绘制几何图形
应用程序(网页、桌面应用或移动应用)大多数都是由基本的几何图形构成的。那我们该如何使用 Skia 绘制基本的几何图形。 画矩形 void drawRect(SkCanvas* canvas) {SkPaint paint;paint.setColor(SK_ColorRED);paint.setStroke(true);paint.setStrokeWid…...

spring:实例化类过程中方法执行顺序。
如题。在实例化Bean时,会根据配置依次调用方法。在此测试代码如下: 在测试类中继承接口InitializingBean,接口InterfaceUserService(该接口为自定义,只是定义set方法)。 InterfaceUserService,…...

设置应用程序图标
(1)找一张图片 (2)然后转ico图片 在线生成透明ICO图标——ICO图标制作 验证16x16就可以 降低exe大小 (3) 在xxx.pro修改 添加 (4) 删除 build 和 xxxpro_user文件 (5)编译project 和运行xx.exe (6)右键 设置快捷方式...

「基于连续小波变换(CWT)和卷积神经网络(CNN)的心律失常分类算法——ECG信号处理-第十五课」2025年6月6日
一、引言 心律失常是心血管疾病的重要表现形式,其准确分类对临床诊断具有关键意义。传统的心律失常分类方法主要依赖于人工特征提取和经典机器学习算法,但这些方法往往受限于特征选择的主观性和模型的泛化能力。 随着深度学习技术的发展,基于…...

用go从零构建写一个RPC(4)--gonet网络框架重构+聚集发包
在追求高性能的分布式系统中,RPC 框架的底层网络能力和数据传输效率起着决定性作用。经过几轮迭代优化,我完成了第四版本的 RPC 框架。相比以往版本,这一版本的最大亮点在于 重写了底层网络框架 和 实现了发送端的数据聚集机制,这…...

OpenBayes 一周速览|TransPixeler 实现透明化文本到视频生成;统一图像定制框架 DreamO 上线,一键处理多种图像生成任务
公共资源速递 2 个公共数据集: * s1K-1.1 数学推理数据集 * HPA 人类蛋白质图谱数据集 3 个公共模型: * MedGemma-4B-IT * Devstral-Small-2505 * DeepSeek-Prover-V2-7B 12 个公共教程: 视频生成 * 2 语音交互 * 3 代码生成 * 3 …...
视频的分片上传,断点上传
上传功能的实现,点击上传按钮,判断添加的文件是否符合要求,如果符合把他放入文件列表中,并把他的状态设置为等待中,对于每个文件,把他们切分为chunksize大小的文件片段,再检查他的状态是否为…...
CSS 性能优化
目录 CSS 性能优化CSS 提高性能的方法1. 选择器优化1.1 选择器性能原则1.2 选择器优化示例 2. 重排(Reflow)和重绘(Repaint)优化2.1 重排和重绘的概念2.2 触发重排的操作2.3 触发重绘的操作2.4 优化重排和重绘的方法 3. 资源优化3…...