我可以在 Linux 中执行写时复制 memcpy 吗?
- 2024-11-14 08:30:00
- admin 原创
- 18
问题描述:
我有一些代码,我经常复制一大块内存,但通常只对其进行很小的更改。
我已经实现了一个跟踪更改的系统,但我认为如果可能的话,告诉操作系统对内存进行“写时复制”,并让它只处理更改部分的复制,这样可能会更好。然而,虽然 Linux 确实进行写时复制,例如在 fork() 时,但我找不到控制它并自己执行的方法。
解决方案 1:
最好的机会可能是将mmap()
原始数据保存到文件中,然后mmap()
再次使用同一个文件MAP_PRIVATE
。
解决方案 2:
根据您复制的具体内容,持久数据结构可能是解决您问题的一种方法。
解决方案 3:
使用面向对象语言(如 C++)实现写时复制更容易。例如,Qt 中的大多数容器类都是写时复制的。
当然,如果您也可以在 C 中做到这一点,那只是需要做更多的工作。当您想要将数据分配给新的数据块时,您不需要进行复制,而是只需复制数据包装器 strcut 中的指针即可。您需要在数据块中跟踪数据的状态。如果您现在更改了新数据块中的某些内容,则需要进行“真实”复制并更改状态。当然,您不能再使用简单的运算符(如“=”)进行赋值,而是需要使用函数(在 C++ 中,您只需进行运算符重载)。
更强大的实现应该使用参考计数器而不是简单的标志,我把它留给你。
举个简单粗暴的例子:如果你有一个
struct big {
//lots of data
int data[BIG_NUMBER];
}
您必须自己实现分配函数和 getter/setter。
// assume you want to implent cow for a struct big of some kind
// now instead of
struct big a, b;
a = b;
a.data[12345] = 6789;
// you need to use
struct cow_big a,b;
assign(&a, b); //only pointers get copied
set_some_data(a, 12345, 6789); // now the stuff gets really copied
//the basic implementation could look like
struct cow_big {
struct big *data;
int needs_copy;
}
// shallow copy, only sets a pointer.
void assign(struct cow_big* dst, struct cow_big src) {
dst->data = src.data;
dst->needs_copy = true;
}
// change some data in struct big. if it hasn't made a deep copy yet, do it here.
void set_some_data(struct cow_big* dst, int index, int data } {
if (dst->needs_copy) {
struct big* src = dst->data;
dst->data = malloc(sizeof(big));
*(dst->data) = src->data; // now here is the deep copy
dst->needs_copy = false;
}
dst->data[index] = data;
}
您还需要编写构造函数和析构函数。我强烈建议使用 c++ 来完成这项工作。
解决方案 4:
例如 fork() 所采用的写时复制机制是 MMU(内存管理单元)的一项功能,它负责处理内核的内存分页。访问 MMU 是一项特权操作,也就是说,用户空间应用程序无法执行此操作。我也不知道有任何写时复制 API 导出到用户空间。
(再说一次,我并不是 Linux API 方面的专家,所以其他人可能会指出我错过的相关 API 调用。)
编辑:瞧,MSalters 不负众望。;-)
解决方案 5:
您应该能够通过 /proc/$PID/mem 打开您自己的内存,然后使用 MAP_PRIVATE 将其有趣的部分 mmap() 到其他地方。
解决方案 6:
这是一个有效的例子:
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define SIZE 4096
int main(void) {
int fd = shm_open("/tmpmem", O_RDWR | O_CREAT, 0666);
int r = ftruncate(fd, SIZE);
printf("fd: %i, r: %i
", fd, r);
char *buf = mmap(NULL, SIZE, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
printf("debug 0
");
buf[SIZE - 2] = 41;
buf[SIZE - 1] = 42;
printf("debug 1
");
// don't know why this is needed, or working
//r = mmap(buf, SIZE, PROT_READ | PROT_WRITE,
// MAP_FIXED, fd, 0);
//printf("r: %i
", r);
char *buf2 = mmap(NULL, SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE, fd, 0);
printf("buf2: %i
", buf2);
buf2[SIZE - 1] = 43;
buf[SIZE - 2] = 40;
printf("buf[-2]: %i, buf[-1]: %i, buf2[-2]: %i, buf2[-1]: %i
",
buf[SIZE - 2],
buf[SIZE - 1],
buf2[SIZE - 2],
buf2[SIZE - 1]);
unlink(fd);
return EXIT_SUCCESS;
}
为了安全起见,我有点不确定是否需要启用注释掉的部分。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件