写时拷贝技术(COW)

【Linux】写时复制(CopyOnWrite)|写时拷贝|rcu 什么是写时拷贝 写时拷贝(copy-on-write, COW)就是等到修改数据时才真正分配内存空间,这是对程序性能的优化,可以延迟甚至是避免内存拷贝,当然目的就是避免不必要的内存拷贝。 阅读详情

写时拷贝技术

  写时拷贝技术实际上是一种拖延战术,是为了提高效率而产生的技术,这怎么提高效率呢?实际上就是在需要开辟空间时,假装开了空间,实际上用的还是原来的空间,减少开辟空间的时间,等到真正要使用新空间的时候才去真正开辟空间。
  举一个例子理解写时拷贝技术:我们小时候经常会遇到这种情况:家里面有哥哥姐姐的,大人们经常会让我们穿哥哥姐姐穿剩的衣服,这样看起来我们就有了新衣服,但实际上我们穿的还是哥哥姐姐的旧衣服,等到我们真的长大了,才会给我们买属于自己的新衣服,这样节省了给我们买衣服的时间和财力。从而节省了很多资源(提高效率)。等我们真的需要时才不得不买新衣服(拖延战术)。
在这里插入图片描述

写时拷贝技术原理

  写时拷贝技术实际上是运用了一个 “引用计数” 的概念来实现的。在开辟的空间中多维护四个字节来存储引用计数。
有两种方法:
①:多开辟四个字节(pCount)的空间,用来记录有多少个指针指向这片空间。
②:在开辟空间的头部预留四个字节的空间来记录有多少个指针指向这片空间。
  当我们多开辟一份空间时,让引用计数+1,如果有释放空间,那就让计数-1,但是此时不是真正的释放,是假释放,等到引用计数变为 0 时,才会真正的释放空间。如果有修改或写的操作,那么也让原空间的引用计数-1,并且真正开辟新的空间。

linux 下的 fork() 就是用的写时拷贝技术,引用计数不光在 string 这里用到,还有智能指针 shared_ptr 也用到了引用计数来解决拷贝问题。

举个例子

string 的写时拷贝(维护一个指针):

class String
{
public:
	//构造
	String(const char* str)
		:_str(new char[strlen(str) + 1])
		,_pCount(new int(1))
	{
		strcpy(_str, str);
	}

	//拷贝构造
	String(const String& s)
		:_str(s._str)
		,_pCount(s._pCount)
	{
		(*_pCount)++;
	}

	//赋值运算符重载
	String& operator=(const String& s)
	{
		if(_str != s._str)
		{
			if(--(*_pCount) == 0)
			{
				delete[] _str;
				delete _pCount;
			}
			_str = s._str;
			_pCount = s._pCount;
			(*_pCount)++;
		}
		return *this;
	}

	~String()
	{
		if(--(*_pCount) == 0)
		{
			delete[] _str;
			delete _pCount;
		}
	}

	char& operator[](size_t pos)
	{
		if(*_pCount > 1)
		{
			char* newstr = new char[strlen(_str) + 1];
			strcpy(newstr, _str);
			--(*_pCount);
			_str = newstr;
			_pCount = new int(1);
		}
		return _str[pos];
	}

	const char* c_str()
	{
		return _str;
	}
private:
	char* _str;
	int* _pCount;
};

源码中的写法:在空间的头部维护四个字节的空间,记录引用的个数。放在头部维护效率能高一些,如果放在尾部维护的话,每次开辟新的空间都要讲这四个字节也向后挪动相应的位置,所以放在前面效率高点

class String
{
public:
	//构造
	String(const char* str)
		:_str(new char[strlen(str) + 4 + 1])
	{
		_str += 4;		//前四个字节放引用计数
		strcpy(_str, str);
		GetRefCount() = 1;
	}

	//拷贝构造
	String(const String& s)
		:_str(s._str)
	{
		GetRefCount()++;
	}

	//赋值运算符重载
	String& operator=(const String& s)
	{
		if(_str != s._str)
		{
			if(--GetRefCount() == 0)
			{
				delete[] (_str - 4);
			}
			_str = s._str;
			GetRefCount()++;
		}
		return *this;
	}

	~String()
	{
		if(--GetRefCount() == 0)
		{
			delete[] (_str - 4);
			_str = nullptr;
		}
	}

	char& operator[](size_t pos)
	{
		if(GetRefCount() > 1)
		{
			--GetRefCount();
			char* newstr = new char[strlen(_str) + 4 + 1];
			newstr += 4;
			strcpy(newstr, _str);
			_str = newstr;
			GetRefCount() = 1;
		}
		return _str[pos];
	}

	int& GetRefCount()
	{
		return *((int*)(_str - 4));		//前四个字节为引用计数
	}
private:
	char* _str;
};
SOI技术解析:绝缘体上硅的结构优势与应用场景 本文深入解析了SOI(绝缘体上硅)技术的核心结构、性能优势与应用场景。SOI通过在硅衬底与器件层之间引入绝缘的埋氧层,实现了优异的电隔离,从而显著降低芯片功耗、提升工作频率并增强抗干扰能力。该技术已广泛应用于5G射频前端、高性能计算、汽车电子及MEMS传感器等关键领域,是推动半导体性能持续提升的重要技术路径。 阅读详情

相关推荐

MFC+Modbus-Tcp协议实现温湿度传感器采集

本文简单介绍MFC使用-Tcp通信实现系列MODBUSTCP型温湿度传感器采集数据。

zhigang_zhao的博客 2830

Redis 笔记三 RDB执行流程

RDB执行流程(原理) 1. Redis父进程首先判断:当前是否在执行save,或bgsave/bgrewriteaof(aof文件重写命令)的子进程,如果在执行则bgsave命令直接返回。 2. 父进程执行fork(调用OS函数复制主进程)操作创建子进程,这个复制过程中父进程是阻塞的,Redis不能执行来自客户端的任何命令。 3. 父进程fork后,bgsave命令返回”Background saving started”信息并不再阻塞父进程,并可以响应其他命令。 4. 子进程创建RDB文件,

文报的博客 2138

Ceres-solver examples之pose_graph_3d学习笔记

Ceres-solver examples之pose_graph_3d学习笔记简要说明变量说明关键步骤一、Costfunction的搭建其中包括:二、构造Problem 简要说明 ceres-solver库是google的非线性优化库,可以对slam问题,机器人位姿进行优化,使其建图的效果得到改善。pose_graph_3d是官方给出的二维平面上机器人位姿优化问题,需要读取一个g2o文件,运行程序...

幽冥小龙的博客 3890

Linux写时拷贝技术(copy-on-write)

源于网上资料 COW技术初窥:       在Linux程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,linux中引入了“写时复制“技术,也就是只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程。       那么子进程的物理空间没有代码,怎么去取指令执行exec系统调用呢?       在fork之后exe...

weixin_33923148的博客 1109

PEMFC电化学入门:从电流密度到Tafel公式的实战计算指南

本文详细介绍了PEMFC电化学的基础知识,从电流密度计算到Tafel公式的应用,提供了实战计算指南。通过代码示例和常见问题排查,帮助工程师快速掌握燃料电池性能优化的关键参数,如交换电流密度和活化损失计算,适用于汽车动力和分布式发电等领域。

weixin_29229055的博客 551

我看MFC的过去、现在和未来

首先说句题外话,虽然我现在的“主业”是Qt,但自己扪心自问,对MFC的熟悉程度要超过Qt。正是由于有了对MFC的熟悉,才能在使用Qt时,比较清醒的认清两者的优劣之处,在此暂且不提。 这个话题也可以说是由来已久,众说纷纭,今时我也谈谈自己的感悟。 一、对MFC的总体看法 首先看看云风在其《游戏之旅-我的编程感悟》一书中对MFC的看法: “我所见到的程序员中,很多把C+

qter_wd007的专栏 6115

Linux下fork与写时拷贝技术(COW)详解

1. 写时拷贝的概念 Linux在使用fork()函数进程创建时,传统fork()的做法是系统把所有的资源复制给新创建的进程,这种方式不仅单一,而且效率低下。因为所拷贝的数据或别的资源可能是可以共享的。现在Linux的fork()使用写时拷贝页来实现新进程的创建,它是一种可推迟甚至避免数据拷贝的技术,刚开始时内核并不会复制整个地址空间,而是让父子进程共享地址空间,只有在写时才复制地址空间,使得父子...

Ternence_zq的博客 4136

倍福ADS通讯协议深度解析——从握手到数据包的完整旅程

本文以工程师视角,通过Wireshark抓包实战,深度解析了倍福ADS通讯协议的完整工作流程。从TCP三次握手建立连接,到拆解AMS/TCP信封、AMS Header地址与命令解析,再到ADS Data读写请求的载荷构成,完整呈现了一次数据通讯的“旅程”。文章重点剖析了协议包格式,并结合实际案例,提供了基于协议分析的故障排查思路,帮助开发者深入理解并精准调试工业自动化系统通讯。

weixin_29231725的博客 151

六、C++语言进阶:写时拷贝技术

写时拷贝技术

小脑斧的博客 779

芯片原厂linux驱动开发的分享

大家好,我是XX,来自湖南XX学院,电子信息18级,也曾在创新基地控制组学习过两三年,毕业后就职于一家芯片原厂的解决方案部,担任驱动工程师的职位,算上实习期,我的工作时长已有两年。在此我想将这两年期间学习与积累到的一些经验输出出来,与大家一同分享。知识面有限,只能简单介绍一些驱动开发方向的一些经验,且由于经验尚浅,文中难免会有一些疏漏和错误之处,还请大家积极地批评指正。

嵌入式技术开发 847

innovus:addRepeaterByRule用法

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧?addRepeaterByRule不管transition/timing violation,只根据约束的length/cap/fanout等等去给net 插buffer。

m0_61544122的博客 1091

Linux:COW 写时拷贝技术

操作系统一:COW:Copy-On-Write 写时拷贝技术 1. cow 写时拷贝技术的背景1.1 传统fork()调用1.2 传统fork()调用的缺点2. cow 写时拷贝:2.1 一句话解释:虚拟地址空间独立(复制),物理地址空间共享,只有写入时才拷贝(推迟或者避免拷贝)2.2 cow 写时拷贝技术原理2.3 cow 写时拷贝的不拷贝的情形:exec2.4 cow 应用场景 1. cow 写时拷贝技术的背景 1.1 传统fork()调用 传统的fork()系统调用直接把所有的资源复制给新创建的进

哈尼的博客 1379

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

写时拷贝(copy-on-write) COW技术

一、写时拷贝的概念——COW技术在Linux进程上的应用 Linux在使用fork()函数进程创建时,传统fork()的做法是系统把所有的资源复制给新创建的进程,这种方式不仅单一,而且效率低下。因为所拷贝的数据或别的资源可能是可以共享的。现在Linux的fork()使用写时拷贝页来实现新进程的创建,它是一种可推迟甚至避免数据拷贝的技术,刚开始时内核并不会复制整个地址空间,而是让父子进...

zzhongcy的专栏 2632

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

cow(写时拷贝)技术

此博客已迁移到新博客欢迎大家访问关注,谢谢!!!       在Linux程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,linux中引入了“写时复制“技术,也就是只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程。       那么子进程的物理空间没有代码,怎么去取指令执行exec系统调用呢?       在fork

悲伤逆流的博客 4484

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

【Linux】写时拷贝技术COW (copy-on-write)

肤浅的来说,加载到内存中的程序就叫做进程。但这并不完善。运行中的系统存在大量的进程,操作系统该如何管理这些进程呢?那写实拷贝技术又什么作用呢?

Z1tai的博客 2165

【存储】快照备份技术写时重定向ROW和写时拷贝COW区别|小IO聚合

ROW(Redirect-on-Write):ROW在写入数据的时候直接写入到快照卷;读源卷时,创建快照前的数据从源卷读,创建快照后产生的数据,从快照卷读。 COW(Copy-on-Write):COW就是每当你写入数据之前,快照先对源卷数据进行复制,然后新数据才写进源卷;快照进行读操作时,首先由快照系统判断,上层业务需要读取的数据是否在快照卷中,若在...

小鱼菜鸟的博客 1088

Linux写时拷贝(COW)

COW技术初窥: 在Linux程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,linux中引入了“写时复制“技术,也就是只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程。 那么子进程的物理空间没有代码,怎么去取指令执行exec系统调用呢? 在fork之后exec之前两个进程用...

团长的专栏 2230

Linux写时拷贝技术(copy-on-write)--COW

Linux写时拷贝技术(copy-on-write) 源于网上资料 COW技术初窥:       在Linux程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,linux中引入了“写时复制“技术,也就是只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程。       那么子进程的物理空间没有代码,怎么去取

IT_small_farmer的专栏 1199

linux进程写时拷贝技术cow(copy-on-write)

Linux程序中,创建进程使用的是fork()函数,它会产生一个核父进程基本完全相同的子进程,这里先记住有相同的物理内存,区别仅仅在于pid、ppid和某些统计量。子进程后面基本都会执行exec系统调用,它会引起子进程另起内存拷贝一份,如果创建子进程都需要拷贝内存的话,辛苦拷贝的又完全放弃了,出于效率考虑,Linux引入了写时复制技术,也就是只有进程空间的各段内容要发生变化时,才会将父进程的内容复制一份给子进程。 在fork之后exec之前两个进程用的是相同的物理空间(内存...

夏天Alex 1823

写时拷贝技术(copy-on-write)

传统的fork()系统调用直接把所有的资源复制给新创建的进程。这种实现过于简单并且效率低下,因为它拷贝的数据也许并不共享,更糟的情况是,如果新进程打算立即执行一个新的映像,那么所有的拷贝都将前功尽弃。Linux的fork()使用写时拷贝(copy-on-write)页实现。写时拷贝是一种可以推迟甚至免除拷贝数据的技术。内核此时并不复制整个进程地址空间,而是让父进程和子进程共享同一个拷贝。只有在需要

The Coding World 4642

COW

Linux写时拷贝技术(copy-on-write) 源于网上资料 COW技术初窥:       在Linux程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,linux中引入了“写时复制“技术,也就是只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程。       那么子进程的物理空间没

screaming的博客 303

存储系统的Snapshot快照技术(COW与ROW)

快照创建以后,若上层业务对源卷写数据X,X在缓存中排队,快照系统判断X即将写入源卷的逻辑地址,然后将数据X写入快照卷中预留的对应逻辑地址中,同时,将源卷和快照卷的逻辑地址写入映射表,即写重定向。若快照创建以后,上层业务对源卷进行读,则有两种情况:1)若读取的数据,在创建快照前产生,数据是保存在源卷上的,那么,上层就从源卷进行读取;若快照创建以后,上层业务对快照卷进行读,同样也有两种情况:1)若读取的数据,在创建快照前产生,数据是保存在源卷上的,那么上层就查询映射表,从源卷进行读取;

wangjingbin的专栏 2188

【存储】快照|写时重定向ROW和写时拷贝COW|RWM|小IO聚合

概念 要解决的问题,快照究竟是在备份什么? 全球网络存储工业协会SNIA(Storage Networking Industry Association)对快照(Snapshot)的定义是:关于指定数据集合的一个完全可用拷贝,该拷贝包括相应数据在某个时间点(拷贝开始的时间点)的映像(和索引----本人添加)。 快照可以是其所表示的数据的一个副本,也...

小鱼菜鸟的博客 1123

进程线程(二) fork、vfork、clone,写时拷贝(cow技术)

我们知道 进程是资源的单位,线程是调度的单位。也就是说每个进程都有自己独立的资源,独立的 task_struct , 那我们如何去理解 fork 的时候,资源是怎么分割出一个新的资源呢? linux 中著名的COW 写实拷贝 例子 子进程修改全局变量,修改完后,父进程再打印该全局变量,会变化吗,答案是不变的。 这就是著名的Copy on write 技术,是依赖硬件MMU的,没有MMU,就不支持 fork,只支持vfork。 当fork的时候,所有的资源都好分裂,除了 mm内存资源, ..

只有自己觉到悟到的,才是自己的。 1034
上一篇: 重载、重写、隐藏是什么?
下一篇: C++之继承
coolnut12138
博客等级 码龄9年 51粉丝 75原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值