C++ 如何";使用write()系统调用从页面读取(写入虚拟管道()文件描述符)";在C/C++;?

C++ 如何";使用write()系统调用从页面读取(写入虚拟管道()文件描述符)";在C/C++;?,c++,c,pointers,memory,C++,C,Pointers,Memory,我需要测试内存地址是否可读,所以我搜索并发现了这个问题: 正如user@caf所述: 规范的方法是使用write()系统调用从页面读取(写入虚拟管道()文件描述符) 不幸的是,他没有提供任何代码示例,我也不能评论(低声誉)也不能给他发消息(至少我不知道怎么做) 编辑 我就不能通过这样做来省略创建管道吗 int result = write(0, addr, 1); @Mats Peterson:我正在尝试在使用函数指针将函数加载到内存后分析和更改它(我正在递增指针并逐字节复制它的值),所以要确

我需要测试内存地址是否可读,所以我搜索并发现了这个问题: 正如user@caf所述:

规范的方法是使用write()系统调用从页面读取(写入虚拟管道()文件描述符)

不幸的是,他没有提供任何代码示例,我也不能评论(低声誉)也不能给他发消息(至少我不知道怎么做)

编辑

我就不能通过这样做来省略创建管道吗

int result = write(0, addr, 1);
@Mats Peterson:我正在尝试在使用函数指针将函数加载到内存后分析和更改它(我正在递增指针并逐字节复制它的值),所以要确定它是否仍然是这个函数,我需要知道内存是否可写和可读(我知道这样做有点愚蠢)。无论如何,我不想更改程序的内存读/写权限,因此您所说的可能是个问题

编辑2
@Damon:那么还有其他可靠的方法可以做到这一点吗?

首先,创建一个管道对将数据写入:

 int fd[2];
 pipe(fd);
然后尝试将一些数据从您的地址写入管道的写入端:

 int result = write(fd[1], addr, 1);
如果
result
为1,则写入成功,因此地址是可读的。如果为零且
errno==EFAULT
,则地址不可读。如果
errno
是其他东西,则是其他东西出了问题

完成后,确保关闭管道,当然:

 close(fd[0]);
 close(fd[1]);

首先,创建要将数据写入的管道对:

 int fd[2];
 pipe(fd);
然后尝试将一些数据从您的地址写入管道的写入端:

 int result = write(fd[1], addr, 1);
如果
result
为1,则写入成功,因此地址是可读的。如果为零且
errno==EFAULT
,则地址不可读。如果
errno
是其他东西,则是其他东西出了问题

完成后,确保关闭管道,当然:

 close(fd[0]);
 close(fd[1]);

我自己从来没有使用过这种方法,但我认为当
向管道写入
时,您必须创建一个管道(使用系统调用),提供您要检查的地址作为缓冲区

因此,假设您想检查地址
0x1000000
,然后您就可以进行检查,例如

int res = write(dummypipe[1], 0x1000000, 1);

如果
res
-1
,则检查
errno==EFAULT
,这表明地址无效。

我本人从未使用过该方法,但我认为在
向提供要检查作为缓冲区的地址的管道写入
时,必须创建一个管道(使用系统调用)

因此,假设您想检查地址
0x1000000
,然后您就可以进行检查,例如

int res = write(dummypipe[1], 0x1000000, 1);

如果
res
-1
,则检查
errno==EFAULT
,这表明地址无效。

注意,此方法存在常见的“toctou”(检查时间到使用时间)问题-检查地址X是否有效,是否有效,由于某些操作(例如关闭管道,但存在数百种其他可能的情况,特别是在多核/多线程系统中),操作系统决定回收该部分内存,而内存不再有效。也许如果您描述了您实际试图解决的问题(如“为什么您认为您需要知道内存是否有效”),我们可以想出更好的解决方案?还请注意,这可能会导致页面错误(假定地址是有效页面),不仅速度慢,但也可能从您的工作集中清除另一个页面。重新编辑:是的,有一种安全有效的方法。只能读取或写入已正确分配的地址(例如,使用
mmap
malloc
)。特别是,不要写入
文本
段中的地址(由于DEP,这可能无论如何都不起作用——不管它是否是有效地址),也不要对编译后的二进制文件中的函数的结束位置进行假设(它可能有2或3个结束点,并且很可能无法填充整个页面)。请注意,此方法存在常见的“toctou”(检查时间到使用时间)问题-您检查地址X是否有效,它是否有效,操作系统决定回收该部分内存作为某些操作的结果[例如关闭管道,但存在数百种其他可能的情况,特别是在多核/多线程系统中]并且内存不再有效。也许如果您描述了您实际试图解决的问题(如“为什么您认为您需要知道内存是否有效”),我们可以想出更好的解决方案?还请注意,这可能会导致页面错误(假定地址是有效页面),不仅速度慢,但也可能从您的工作集中清除另一个页面。重新编辑:是的,有一种安全有效的方法。只能读取或写入已正确分配的地址(例如,使用
mmap
malloc
)。特别是,不要写入
文本
段中的地址(由于DEP,这可能无论如何都不起作用——不管它是否是有效地址),也不要假设编译后的二进制文件中的函数结束于何处(它可能有2或3个端点,并且很可能无法填充整个页面)。