社区
进程/线程/DLL
帖子详情
一个进程怎样访问另一个进程的物理内存?
athunwer
2003-01-09 11:19:14
每一个进程都有自己的4G虚拟内存地址,但是我想访问另一个进程的物理地址;
用COPY_DATA传递地址行吗?也就是传递“要访问的物理地址的LPVOID形式”,进程会不会保护自己的物理地址、虚拟地址?
...全文
1636
13
打赏
收藏
一个进程怎样访问另一个进程的物理内存?
每一个进程都有自己的4G虚拟内存地址,但是我想访问另一个进程的物理地址; 用COPY_DATA传递地址行吗?也就是传递“要访问的物理地址的LPVOID形式”,进程会不会保护自己的物理地址、虚拟地址?
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
13 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
NowCan
2003-01-10
打赏
举报
回复
icelight,那是虚拟内存。
喝醉的咖啡
2003-01-10
打赏
举报
回复
ring0
athunwer
2003-01-09
打赏
举报
回复
偶知道共享内存,但是方法是什么?偶从来没接触过,说说大体步骤!
microyzy
2003-01-09
打赏
举报
回复
共享内存
fengge008
2003-01-09
打赏
举报
回复
同意Daniel22_cn(Daniel) 呵呵
icelight
2003-01-09
打赏
举报
回复
GetWindowThreadProcessId( hwnd, &processId );
WriteProcessMemory()
ReadProcessMemory()
demetry
2003-01-09
打赏
举报
回复
在很多情况下,我们都有直接访问物理内存的要求,如在实时高速
数据采集系统中,对I/O板上配置的存储器的访问。但是,为了保证系
统的安全性和稳定性,操作系统并不提倡应用程序直接访问硬件资源,
因此,随着操作系统的进步,导致了目前存在的这样一个不幸的事实:
以前在DOS下很容易实现的特定物理内存的读写操作,在Windows下却
变得相当困难。
本文主要讨论如何在Windows 95/98下实现物理内存的直接读写
操作。为了论述清楚这个问题,有必要叙述保护模式的寻址方式以及W
indows 95/98的内存管理方式。
Windows 95/98内存管理方式
Windows 95/98工作在32位保护模式下,保护模式与实模式的根本
区别在于CPU寻址方式上的不同:尽管两者对应的内存地址均为"段地
址:偏移量"形式,但在保护模式下,"段地址"代表的值已不再是实模式
中段的起始基准地址了;对于CS、DS、ES、SS寄存器,在实模式下,这
些寄存器的值左移4位,再加上偏移量,即得到物理地址,而在保护模式
下,这些寄存器的值为"段选择符",它实际上是一个查全局描述符表(G
DT)或局部描述符表(LDT)的索引,据此在GDT或LDT找到对应的段描述
符,从而获得段的基址及类型等信息,再根据偏移量,才能得到线性地
址。如果操作系统没有采用分页机制,那么得到的线性地址即为物理
地址,否则,线性地址需要进一步经过分页机制才能得到物理地址。这
就是保护模式下的"段页式寻址机制"。
Windows 95/98使用4GB的虚拟内存地址空间,应用程序访问内存
使用虚拟地址,从虚拟地址到物理地址的转换过程如图1所示:
图1 虚拟地址到物理地址的转化过程
对于图1中的分页机制,Windows 95/98采用两级页表结构,如图2
所示。图2 采用的分页机制的两级页表结构
从图2可知,线性地址被分割成页目录条目(PDE)、页表条目(PTE)
、页偏移地址(Off set)三个部分。当建立一个新的WIN 32进程时,Wi
ndows 95/98会为它分配一块内存,并建立它自己的页目录、页表,页
目录的地址也同时放入进程的现场信息中。当计算一个地址时,系统
首先从控制寄存器CR3中读出页目录所在的地址(该地址为物理地址,
并且是页对齐的),然后根据PDE得到页表所在的地址,再根据PTE得到
包含了实际Code或Data的页帧, 最后根据Offset访问页帧中的特定单
元。
常用内存段的段选择符
从上述所介绍的Windows 95/98采用的分段、分页机制可看出,要
想在Windows 95/9 8下直接访问物理内存,关键是得到欲访问物理内
存所在的内存区域对应的段选择符。
一般说来,要求直接访问的物理内存都与实模式下能够寻址的内
存有关(即DOS能直接访问的1M物理内存)。在Windows 3.X中,Microso
ft给出了DOS常用段的段选择符,如_000 0H(未公开),_B800H,_F000H(
已公开),等等,均可以在KERNEL中找到,应用程序可以直接使用这些段
选择符,实现物理内存的直接访问。而在Windows 95/98中,Microsoft
却不在任何文档中提供这些段的预定义,在KERNEL中也不提供相应的
段选择符。但是,Windows 95 /98确实给DOS下的这些常用内存段定义
了相应的段描述符。通过SoftIce 3.02 for Win dows 95/98,我们得
到了关于LDT的如下信息:
......
:ldt
LDTbase=80003000 Limit=3FFF
……
1007 Data16 00000C90 0000FFFF 3 P RW
100F Data16 00000000 0000FFFF 3 P RW
1017 Data16 00000400 0000FFFF 3 P RW
101F Data16 000F0000 0000FFFF 3 P RW
1027 Data16 000A0000 0000FFFF 3 P RW
102F Data16 000B0000 0000FFFF 3 P RW
1037 Data16 000B8000 0000FFFF 3 P RW
103F Data16 000C0000 0000FFFF 3 P RW
1047 Data16 000D0000 0000FFFF 3 P RW
104F Data16 000E0000 0000FFFF 3 P RW
……
其中,每一行对应一个段描述符,第一栏为其段选择符,第二栏为
段描述符的类型,第三栏为段的基地址(线性地址),第四栏为段的限长
,第五栏为段描述符的特权级,第六栏标志对应段是否存在于内存中,
第七栏表示段的访问权限。
可以看出,这些段的基地址与DOS下的常用内存段完全吻合,并且
均为16位的数据段, 限长为64K(0XFFFF),供应用程序访问,都存在于
内存中,可读写。实践证明,这些段就是D OS的常用内存段,也就是说,
这里的线性地址即为物理地址。因此,可以用这些段选择符对相应的
物理内存进行访问。
从程序运行的健壮性考虑,不应该直接应用上述段选择符,而应该
用GetThreadSelec torEntry()函数得到欲访问物理内存对应的段选
择符,该API函数的原型定义为
BOOL GetThreadSelectorEntry (
HANDLE hThread,
// handle of thread that contains selector
DWORD dwSelector,
// number of selector value to look up
LPLDT_ENTRY lpSelectorEntry
// address of selector entry structure
);
其中,LDT_ENTRY的结构定义如下
typedef struct _LDT_ENTRY { // ldte
WORD LimitLow;
WORD BaseLow;
union {
struct {
BYTE BaseMid;
BYTE Flags1;
BYTE Flags2;
BYTE BaseHi;
} Bytes;
struct {
DWORD BaseMid : 8;
DWORD Type : 5;
DWORD Dpl : 2;
DWORD Pres : 1;
DWORD LimitHi : 4;
DWORD Sys : 1;
DWORD Reserved_0 : 1;
DWORD Default_Big : 1;
DWORD Granularity : 1;
DWORD BaseHi : 8;
} Bits;
} HighWord;
} LDT_ENTRY, *PLDT_ENTRY;
用下面的代码可以得到基地址为BASE_DESIRED,限长为0XFFFF的
内存段对应的段选择符:
......
extern CLDTApp theApp;
WORD wSelector; // 内存段对应的段选择符
LDT_ENTRY ldtEntry;
DWORD base, baseMid, baseHigh;
DWORD limit, limitHigh;
for ( WORD sel = 7; sel <= 0xffff; sel +=8 ) {
if (::GetThreadSelectorEntry ( theApp.m_hThread,
DWORD ( sel ), &ldtEntry ) ) {
baseMid = ldtEntry . HighWord . Bytes . BaseMid;
baseMid <<= 16;
baseHigh = ldtEntry . HighWord . Bytes . BaseHi;
baseHigh <<= 24;
base = ldtEntry . BaseLow + baseMid +
baseHigh;
limitHigh = m_ldtEntry . HighWord . Bits . LimitHi;
limitHigh <<= 24;
limit = limitHigh + m_ldtEntry . LimitLow;
if ( 0xFFFF == limit )
if ( BASE_DESIRED == base ) {
// BASE_DESIRED为内存段对应的基地址
wSelector = sel;
break; }}}
直接访问物理内存的实现
得到了段选择符之后,即可把该段选择符置于相应的段寄存器中(
不能用CS,DS),用该寄存器进行数据访问。需注意的是,任何非法段选
择符写入段寄存器将会导致通用保护错误(General Protection Faul
t)。
下面的代码实现物理内存的读/写操作(段选择符用上述方法得到):
void WriteMemory(WORD sel, DWORD dwOffset, const char * str, UINT length)
{
char cWrite;
for ( UINT i = 0; i < length; i ++ )
{
cWrite = str [i];
_asm {
push es
mov ax, sel
mov es, ax
mov ebx, dwOffset
mov al, cWrite
mov byte ptr es:[ebx], al
inc dwOffset
pop es
}
}
}
void ReadMemory ( WORD sel, DWORD dwOffset,char * str, UINT length )
{
char cRead;
for ( UINT i = 0; i < length; i ++ ) {
_asm {
push es
mov ax, sel
mov es, ax
mov ebx, dwOffset
mov al, byte ptres:[ebx]
mov cRead, al
inc dwOffset
pop es
}
str [i] = cRead;
}
}
本文所用操作系统为中文Windows 95 OSR 2.0以及中文Windows
98,编程环境为Vis ual C++ 5.0。
NowCan
2003-01-09
打赏
举报
回复
物理地址还分进程?
Daniel22_cn
2003-01-09
打赏
举报
回复
对不起,再来说两句,你千万不要传递地址,我敢保证,你这样做,你的应用程序会当掉。。因为指针指向的内容在两个进程中是完全不同的。你传递地址,再使用该指针访问时,指针会指向了完全不同的内容,千万记得,不要这样做。。。
systree
2003-01-09
打赏
举报
回复
使用OpenProcess打开其他进程
Daniel22_cn
2003-01-09
打赏
举报
回复
不可能直接访问一个应用程序的内存。
W32提供了很多种进程间通讯的方法。例如内存共享,消息传递,或者产生CopyDataStruct缓冲区
用法如下:
1.Message:
HANDLE mHandle = FindWindow(....);
SendMessage/PostMessage(mHanlde,....);
2.CopyDataStruct:
COPYDATASTRUCT cds;
memset(&cds,0,sizeof(cds));
cds.dwData = ......;
cds.cbData = ......;
cds.lpData = ......;
3.HANDLE CreateFileMapping(HANLDE mFile,
LPSECURITY_ATTIRBUTES lpFileMapping,
DWORD,
DWORD,
DWORD,
LPCTSTR);
较高层次的通讯还可以使用Anonymous Pipes,Named Pipes,Mailslots,OLE automation,DDE 什么的,其他我就不知道了。
snollow
2003-01-09
打赏
举报
回复
1.共享名一定要独树一帜(否则就有可能因为与系统级别的对象同名而导致失败。虽然概率不大,但不得不防:)。
2.在CreateFileMapping(...),OpenFileMapping(...),MapViewOfFile(..)函数中,映射的打开方式参数最好是一致的(否则有些问题令你头晕~~:)。
3.每用MapViewOfFile(...)函数映射一次,都必须UnmapViewOfFile(...)一次。
4.函数调用顺序问题:
a.CreateFileMapping(...)/OpenFileMapping(...);
b.MapViewOfFile(...);
//...操作...
c.UnmapViewOfFile(...);
d.CloseHandle(...);
snollow
2003-01-09
打赏
举报
回复
http://www.codeproject.com/threads/sm.asp
Windows内核-内存管理
- Windows内存管理主要学习什么 - 线性地址是如何管理的 - 物理地址是如何管理的 - 缺页异常解决了什么问题 - 堆,栈这些内存是怎么申请的 - Windows内核情景分析 第三章 - 不管什么程序,除了程序代码本身所占用的空间外,程序在运行过程中总得使用一定的内存空间,因为数据也要占用空间。这些存储数据的内存空间大致可分为三类: - 全局变量:编译工具链接的时候就静态的分配好了 - 局部变量:调用子函数的时候,在栈上分配 - 通过malloc分配,可以通过free释放,重复利用 - 每个
进程
都有4GB的空间,但是这4GB空间并不是都在使用,有没有
一个
地方在记录着哪些地址空间已经使用了,哪些没有使用? - 肯定有
一个
地方在记录 - 怎么记录线性地址是否是可以用的? - 每个
进程
都有自己的线性地址管理
详解
进程
的虚拟内存,
物理内存
,共享内存
目录 写在前面: 一、关于内存的两个概念 1.1 虚拟内存 1.2 驻留内存 二、详解top命令中VIRT、RES和SHR 2.1 top命令中ⅥRT、RES和SHR的含义 三、
进程
的smaps文件 写在前面: 想必在Linux上写过程序的同学都有分析
进程
占用多少内存的经历,或者被问到这样的问题,你的程序在运行时占用了多少内存(
物理内存
)? 通常我们可以通过top命令查看
进程
占用了多少内存。这里我们可以看到VIRT、RES和SHR三个重要的指标,他们分别代表什么意思呢?这是本文需要跟.
如何查看
进程
占用内存的大小以及
物理内存
和虚拟内存的区别
概述 想必在linux上写过程序的同学都有分析
进程
占用多少内存的经历,或者被问到这样的问题——你的程序在运行时占用了多少内存(
物理内存
)?通常我们可以通过top命令查看
进程
占用了多少内存。这里我们可以看到VIRT、RES和SHR三个重要的指标,他们分别代表什么意思呢?这是本文需要跟大家一起探讨的问题。当然如果更加深入一点,你可能会问
进程
所占用的那些
物理内存
都用在了哪些地方?这时候to...
PCB与
进程
分配资源、虚拟内存与
物理内存
、
进程
共享
一、PCB与
进程
分配资源 PCB PCB(progress control block),
进程
控制块。这里先不讨论PCB是什么,其实
进程
这个概念本身就是
一个
很难理解的概念,当
一个
可执行程序被系统执行了以后,就变成了
一个
进程
。那么这个
进程
中到底有什么东西呢,系统究竟给这个
进程
分配了哪些资源?另外,
进程
在内存中的存储是怎么样的? 对于
一个
进程
,它在被执行前其实是
一个
可执行程序。这个程序是被放在磁...
(面经总结)一篇文章带你学会
物理内存
和虚拟内存
文章目录一、
物理内存
和虚拟内存的关系二、
进程
的虚拟地址空间如何分配?三、为什么引入虚拟内存?四、虚拟内存
访问
流程? 一、
物理内存
和虚拟内存的关系
物理内存
:计算机实际的内存大小,也就是计算机安装内存条的大小 虚拟内存:是创建
进程
时分配的虚拟内存,是
一个
地址连续的地址空间 分配的虚拟内存:每个
进程
都认为自己拥有4G的空间,这只是每个
进程
认为的,但是实际上,在虚拟内存对应的
物理内存
上,可能只对应的一点点的
物理内存
,实际用了多少内存,就会对应多少
物理内存
。 二、
进程
的虚拟地址空间如何分配? 每个程序被运行起来之后
进程/线程/DLL
15,471
社区成员
49,182
社区内容
发帖
与我相关
我的任务
进程/线程/DLL
VC/MFC 进程/线程/DLL
复制链接
扫一扫
分享
社区描述
VC/MFC 进程/线程/DLL
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章