社区
进程/线程/DLL
帖子详情
一个进程怎样访问另一个进程的物理内存?
athunwer
2003-01-09 11:19:14
每一个进程都有自己的4G虚拟内存地址,但是我想访问另一个进程的物理地址;
用COPY_DATA传递地址行吗?也就是传递“要访问的物理地址的LPVOID形式”,进程会不会保护自己的物理地址、虚拟地址?
...全文
1707
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
在NT中直接
访问
物理内存
P.bhw98{ PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 9pt; PADDING-BOTTOM: 0px; MARGIN: 10px 0px 5px; LINE-HEIGHT: normal; PADDING-TOP: 0px; FONT-FAMIL
物理内存
和虚拟内存
1.概念
物理内存
:真实的硬件设备(内存条) 虚拟内存:利用磁盘空间虚拟出的一块逻辑内存,用作虚拟内存的磁盘空间被称为交换空间(Swap Space)。(为了满足
物理内存
的不足而提出的策略) 在很久以前,还没有虚拟内存概念的时候,程序寻址用的都是物理地址,取决于CPU的地址线条数,32位平台的话 2^32也就是4G 。且每次开启
一个
进程
都给4G的
物理内存
。很显然你内存小一点,这很快就分配完了,于...
详解
进程
的虚拟内存,
物理内存
,共享内存
目录 写在前面: 一、关于内存的两个概念 1.1 虚拟内存 1.2 驻留内存 二、详解top命令中VIRT、RES和SHR 2.1 top命令中ⅥRT、RES和SHR的含义 三、
进程
的smaps文件 写在前面: 想必在Linux上写过程序的同学都有分析
进程
占用多少内存的经历,或者被问到这样的问题,你的程序在运行时占用了多少内存(
物理内存
)? 通常我们可以通过top命令查看
进程
占用了多少内存。这里我们可以看到VIRT、RES和SHR三个重要的指标,他们分别代表什么意思呢?这是本文需要跟.
进程
能否
访问
另
一个
进程
的资源
进程
之间不能直接
访问
彼此私有资源,但可通过 IPC 实现共享
访问
。其中。
linux监测指定
进程
的CPU及
物理内存
消耗情况(c程序)
近日,由于工作要求,研究了一下如何在linux系统下对某个指定的单个
进程
进行监测,分析其CPU及
物理内存
的使用情况,并基于c语言写了
一个
独立的模块,完整的实现上述功能。现将整个模块的代码贴上,以便日后借鉴,并与同道中人分享。源码在ubuntu 16.04、嵌入式主板等多个系统下运行亲测正常,各类注释都比较齐全,对模块的使用方法也有介绍,此处就不再赘述,若有问题,自行阅读源码即可。 注:另有一份代码...
进程/线程/DLL
15,465
社区成员
49,169
社区内容
发帖
与我相关
我的任务
进程/线程/DLL
VC/MFC 进程/线程/DLL
复制链接
扫一扫
分享
社区描述
VC/MFC 进程/线程/DLL
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章