Linux系统下追加记录到文件中的实例代码解读
今日阅读Linux程序设计第四版,找到一个使用mmap函数的实例
问题描述




该程序主要定义一个结构体,随后利用mmap,msync以及munmap函数对其进行内容追加,定位以及修改内容的操作。
先自己实现该代码,随后进行编译
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdlib.h>
typedef struct{
int integer;
char string[24];
} RECORD;
#define NRECORDS (100)
int main()
{
RECORD record, *mapped;
int i, f;
FILE *fp;
fp = fopen("records.dat","w+");
for(i = 0 ; i < NRECORDS; i++)
{
record.integer = i;
sprintf(record.string,"RECORD-%d",i);
fwrite(&record,sizeof(record),1,fp);
}
fclose(fp);
fp = fopen("records.dat","r+");
fseek(fp,43*sizeof(record),SEEK_SET);
fread(&record,sizeof(record),1,fp);
record.integer = 143;
sprintf(record.string,"RECORD-%d",record.integer);
fseek(fp,43*sizeof(record),SEEK_SET);
fwrite(&record,sizeof(record),1,fp);
fclose(fp);
f = open("records.dat",O_RDWR);
mapped = (RECORD *)mmap(0,NRECORDS*sizeof(record),PROT_READ|PROT_WRITE,MAP_SHARED,f,0);
mapped[43].integer = 243;
sprintf(mapped[43].string,"RECORD-%d",mapped[43].integer);
msync((void *)mapped, NRECORDS*sizeof(record),MS_ASYNC);
munmap((void *)mapped,NRECORDS*sizeof(record));
close(f);
exit(0);
}
随后逐行进行解读
RECORD record, *mapped;
int i, f;
FILE *fp;
fp = fopen("records.dat","w+");
for(i = 0 ; i < NRECORDS; i++)
{
record.integer = i;
sprintf(record.string,"RECORD-%d",i);
fwrite(&record,sizeof(record),1,fp);
}
先fopen创建一个records.dat文件,随后for循环100次,每次record结构体内integer整形值+1,将RECORD结构体record内的integer整形值设定为i
使用sprintf函数,发送格式化输出到record的string字符串中,然后使用fread函数,
fwrite 用于写记录,这里的记录是指一串固定长度的字节,比如一个 int、一个结构体或者一个定长数组。
fwrite(&record,sizeof(record),1,fp);
意思为,从fp流中取得1*sizeof(record)个大小的字节,存放到record结构体当中
fp = fopen("records.dat","r+");
fseek(fp,43*sizeof(record),SEEK_SET);
fread(&record,sizeof(record),1,fp);
record.integer = 143;
sprintf(record.string,"RECORD-%d",record.integer);
fseek(fp,43*sizeof(record),SEEK_SET);
fwrite(&record,sizeof(record),1,fp);
fclose(fp);
随后以读的方式打开record.dat文件,
fseek函数专用于重定向流的位置
参数声明
int fseek(FILE *stream, long int offset, int whence)
- stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了流。
- offset -- 这是相对 whence
的偏移量,以字节为单位。 - whence -- 这是表示开始添加偏移 offset 的位置。它一般指定为下列常量之一,其中shence的参数可设置为:
SEEK_SET 文件的开头
SEEK_CUR 文件指针的当前位置
SEEK_END 文件的末尾
fseek(fp,43*sizeof(record),SEEK_SET);
意思为从打开的fp流开头往后第43个record的位置开始操作
fread(&record,sizeof(record),1,fp);
record.integer = 143;
sprintf(record.string,"RECORD-%d",record.integer);
最后将从43号位置开始的record整个读出,放到record变量中,注意,使用指针,此时是从地址读取,因此内存中实际的RECORD【43】也发生了更改,然后将这个位置的string字符数组改为:RECORD-143
fseek(fp,43*sizeof(record),SEEK_SET);
fwrite(&record,sizeof(record),1,fp);
fclose(fp);
将该位置的record重新写回对应内存,关闭这个流
f = open("records.dat",O_RDWR);
mapped = (RECORD *)mmap(0,NRECORDS*sizeof(record),PROT_READ|PROT_WRITE,MAP_SHARED,f,0);
mapped[43].integer = 243;
sprintf(mapped[43].string,"RECORD-%d",mapped[43].integer);
msync((void *)mapped, NRECORDS*sizeof(record),MS_ASYNC);
munmap((void *)mapped,NRECORDS*sizeof(record));
继续打开records.dat文件,采用可读写方式打开
mmap函数用于建立内存映射,并返回映射首地址指针mapped
该步骤将定位到整个RECORD数组的首地址
并修改其中的43号位置的integer
mmap函数详细解释
void* mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset);
- 参数start:指向欲映射的内存起始地址,通常设为 NULL,代表让系统自动选定地址,映射成功后返回该地址
- 参数length:代表将文件中多大的部分映射到内存。
- 参数prot:映射区域的保护方式。可以为以下几种方式的组合:
PROT_EXEC 映射区域可被执行
PROT_READ 映射区域可被读取
PROT_WRITE 映射区域可被写入
PROT_NONE 映射区域不能存取 - 参数flags:影响映射区域的各种特性
- 参数fd:要映射到内存中的文件描述符。
- 参数offset:文件映射的偏移量,通常设置为0
msync((void *)mapped, NRECORDS*sizeof(record),MS_ASYNC);
munmap((void *)mapped,NRECORDS*sizeof(record));
msync函数用于把从传入起始位置开始的修改写回到内存中
munmap函数可用于释放该内存段,将mapped指针指向的部分释放
Linux程序设计第四版一书中对这一部分解释如下:

其实此方法与上一步骤当中的内存映射方法达到目的相同
第一种方法通过定位到流的具体位置做出精确修改,第二种方法通过mmap函数将整个RECORD结构体数组的指针找到,通过该指针找到具体位置。因为在C中,数组本身就是一个指针。
Linux系统下追加记录到文件中的实例代码解读的更多相关文章
- linux系统下如何在vscode中调试C++代码
本篇博客以一个简单的hello world程序,介绍在vscode中调试C++代码的配置过程. 1. 安装编译器 vscode是一个轻量的代码编辑器,并不具备代码编译功能,代码编译需要交给编译器完成. ...
- Linux系统下,在文件中查找某个字符串
在normal模式下按下/即可进入查找模式,输入要查找的字符串并按下回车. Vim会跳转到第一个匹配.按下n查找下一个,按下N查找上一个. Vim查找支持正则表达式,例如/vim$匹配行尾的" ...
- Linux系统下查看某文件修改的时间戳
Linux系统下查看某文件修改的时间戳查看文件时间戳命令:stat awk.txt File: `awk.txt' Size: 20 Blocks: 8 I ...
- Linux系统下运行.sh文件
在Linux系统下运行.sh文件有两种方法,比如我在root目录下有个vip666.sh文件 #chmod +x *.sh的文件名 #./*.sh的文件名 第一种(这种办法需要用chmod使得文件具备 ...
- Linux系统下/tmp目录文件重启后自动删除,不重启自动删除10天前的/TMP的文件(转)
/tmp目录文件重启后自动删除现在知道有ubuntu和solaris系统source:http://blog.chinaunix.net/uid-26212859-id-3567875.html经常会 ...
- [转]Windows与Linux系统下的库文件介绍
什么是库 库文件是一些预先编译好的函数的集合,那些函数都是按照可再使用的原则编写的.它们通常由一组互相关联的用来完成某项常见工作的函数构成,从本质上来说库是一种可执行代码的二进制形式,可以被操作系 ...
- Linux系统下进入目录文件需要什么权限?
在Linux下进入目录需要什么权限? 1--让我们先来了解一下Linux下一个文件有哪些权限?(在linux下一切皆文件) 一个文件可以具有的权限有:可读.可写.可执行权限 r 可读权限---read ...
- 修改Linux系统下的最大文件描述符限制
通常我们通过终端连接到linux系统后执行ulimit -n 命令可以看到本次登录的session其文件描述符的限制,如下: $ulimit -n1024 当然可以通过ulimit -SHn 1024 ...
- 并发时-修改Linux系统下的最大文件描述符限制
通常我们通过终端连接到linux系统后执行ulimit -n 命令可以看到本次登录的session其文件描述符的限制,如下: $ulimit -n1024 当然可以通过ulimit -SHn 1024 ...
- Linux培训教程 linux系统下分割大文件的方法
在linux中分割大文件,比如一个5gb日志文件,需要把它分成多个小文件,分割后以利于普通的文本编辑器读取. 有时,需要传输20gb的大文件,Linux培训 教程件到另一台服务器,也需要把它分割成多个 ...
随机推荐
- Python实验报告(第7章)
实验7:面向对象程序设计 一.实验目的和要求 1.了解面向对象的基本概念(对象.类.构造方法): 2.学会类的定义和使用: 3.掌握属性的创建和修改: 4.掌握继承的基本语法. 二.实验环境 软件版本 ...
- Python 文件操作(IO 技术)
目录 Python 文件操作(IO 技术) 文本文件和二进制文件 文件操作相关模块概述 建文件对象 open() 文本文件的写入 write()/writelines()写入数据 close()关闭文 ...
- Pytorch基础-张量基本操作
一,张量的基本操作 二,维度变换 2.1,squeeze vs unsqueeze 维度增减 2.2,transpose vs permute 维度交换 三,索引切片 3.1,规则索引切片方式 3.2 ...
- css预处理器scss/sass语法以及使用
scss scss在css基础语法上面增加了变量 (variables).嵌套 (nested rules).混合 (mixins).导入 (inline imports) 等高级功能,使用scss可 ...
- ansible离线安装k8s v1.25版本
Kubernetes v1.25 企业级高可用集群自动部署(离线版) 注:确保所有节点系统时间一致 操作系统要求:CentOS7.x_x64 1.找一台服务器安装Ansible # yum insta ...
- Vue 快速入门(一)
1.介绍 Vue(读音/vju/,类似view),是中国的大神尤雨溪开发的,为数不多的国人开发的世界顶级开源软件.是一套用于构建用户界面的渐进式框架,Vue 被设计为可以自底向上逐层应用.MVVM响应 ...
- ClickHouse(11)ClickHouse合并树MergeTree家族表引擎之SummingMergeTree详细解析
目录 建表语法 数据处理 汇总的通用规则 AggregateFunction 列中的汇总 嵌套结构数据的处理 资料分享 参考文章 SummingMergeTree引擎继承自MergeTree.区别在于 ...
- 前端 - JaveScrip
今日内容 JS简介 全程JaveScript但是与Jave没有关系 知识为了蹭Jave热度 它是一门前端工程师的编程语言 但是它本身有很多逻辑错误 IT行业鄙视链:前端.运维.测试.产品 前端想一统天 ...
- (19)go-micro微服务filebeat收集日志
目录 一 Filebeat介绍 二 FileBeat基本组成 三 FileBeat工作原理 四 Filebeat如何记录文件状态: 五 Filebeat如何保证事件至少被输出一次 六 安装Filebe ...
- Django-Django基本使用、app、三板斧
1.纯手撸web框架 1.web框架的本质 理解1:连接前端与数据库的中间介质 理解2:socket服务端 2.手写web框架 1.编写socket服务端代码 2.浏览器访问响应无效>>& ...