前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Linux下如何in-place更改文件

Linux下如何in-place更改文件

原创
作者头像
netkiddy
修改2020-11-02 16:35:30
2.7K0
修改2020-11-02 16:35:30
举报
文章被收录于专栏:非典型程序猿非典型程序猿

导言

前几天下班在地铁上,听到身边有两个小伙子在讨论,如何in-place的修改一个文件,路上想了半天没有好的办法。等到了家里一番探究,终于找到可行的方案了。

什么是in-place的更改文件

所谓edit in place,顾名思义,就是当我们更改一份文件时,不可以创建任何的中间/临时文件,或者临时内存等,来完成对一份文件的修改。

更改文件的典型做法

无论是更改文件,或者更改一块内存,我们的典型做法显然是会想到使用一份临时空间去保存修改的数据,并在之后写回到原始文件/内存中来实现我们的一次更改操作。一个类似的例子,用过linux的话,大家应该都有用过vi/vim去修改一份文件,看起来的行为是直接打开一份文件,然后修改,然后wq保存退出。但是如果有朋友做过监听文件变更的功能的话,会注意到vim在变更文件时,悄悄地去生成了一份隐藏的临时文件,存储了一些中间的变更的数据并在之后再写回到源文件。其实是差不多的道理。

如何做到

那么,我们到底能不能in place的更改一份文件呢?当然是可以的,我们可以使用mmap。通过mmap将文件装载到内存中再去修改它,从而通过让操作系统来处理对变更部分的保存并写回到原文件的操作。在整个过程中,mmap并不分配空间, 只是将文件映射到调用进程的地址空间里,因此我们完成了对文件的操作而不必再调用read,write等系统调用函数,而同一时刻,内核空间对这段区域的修改也直接反映用户空间。

Code

代码语言:javascript
复制
package main

import (
	"os"
	"syscall"
)

func main() {
	edit_in_place("/path/to/file", 0, 'c')
}

func edit_in_place(path string, offset int64, rep byte){
	fd, _ := syscall.Open(path, syscall.O_RDWR, 0)
	
	//获取文件大小
	fi, _ := os.Stat(path)
	
	//映射到内存
	data, _ := syscall.Mmap(
		fd, offset, int(fi.Size()),syscall.PROT_READ|syscall.PROT_WRITE|syscall.PROT_EXEC, syscall.MAP_SHARED)
	defer syscall.Munmap(data)
	
	//update
	data[0]= rep
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 导言
  • 什么是in-place的更改文件
  • 更改文件的典型做法
  • 如何做到
  • Code
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档