通过WriteProcessMemory改写进程的内存

http://www.cnblogs.com/feiyucq/archive/2009/10/21/1587628.html

以PROCESS_ALL_ACCESS权限打开进程以后既能够使用ReadProcessMemory读取程序内存,也能够使用WriteProcessMemory改敲代码的内存,这也是一些内存补丁使用的招数,下面是程序的实现代码

#include <windows.h>
#include <tlhelp32.h>
BOOL CALLBACK EnumChildWindowProc(HWND hWnd,LPARAM lParam);//枚举记事本中的子窗体
char mess[999999];
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
    HWND nphWnd=::FindWindow("notepad",NULL);
    if(nphWnd)
    {
        char temp[1024];
        PROCESSENTRY32 pe32;
        pe32.dwSize=sizeof(pe32);
        HANDLE hProcessSnap=::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);//获得进程列表的快照,第一个參数能够有其它选项,具体请參考MSDN
        if(hProcessSnap==INVALID_HANDLE_VALUE)
        {
            ::MessageBox(NULL,"CreateToolhelp32Snapshot error","error",MB_OK);
            return 0;
        }
        HANDLE hProcess;
        BOOL bMore=::Process32First(hProcessSnap,&pe32);//获得第一个进程的信息
        while(bMore)
        {
            ::wsprintf(temp,"%s",pe32.szExeFile);
            if(!::strcmp(temp,"button.exe"))
            {
                hProcess=::OpenProcess(PROCESS_ALL_ACCESS,false,(DWORD)pe32.th32ProcessID);
                if(hProcess==NULL)
                {
                    ::wsprintf(temp,"%s","打开进程失败!");
                    ::strcat(mess,temp);
                }
                else
                {
                    ::wsprintf(temp,"%s","打开进程成功!");
                    ::strcat(mess,temp);
                    //改写内存中内容
                    int tmp=97;//ascii:a
                    DWORD dwNumberOfBytesRead;
                    if(!::WriteProcessMemory(hProcess,(LPVOID)0x0040505d,&tmp,1,&dwNumberOfBytesRead))
                    {
                        ::wsprintf(temp,"%s","写入失败");
                        ::strcat(mess,temp);
                    }
                    else
                    {
                        ::wsprintf(temp,"%s","写入成功");
                        ::strcat(mess,temp);
                    }
                }
                break;
            }
            bMore=::Process32Next(hProcessSnap,&pe32);//获得其它进程信息
        }
        ::EnumChildWindows(nphWnd,EnumChildWindowProc,0);//获得记事本的edit窗体,打印进程信息
        return 0;
    }
    else
    {
        ::MessageBox(NULL,"please open notepad","error",MB_OK);
        return 0;
    }
}
BOOL CALLBACK EnumChildWindowProc(HWND hWnd,LPARAM lParam)
{
    char temp1[256];
    if(hWnd)
    {
        ::GetClassName(hWnd,temp1,255);
        if(!::strcmp(temp1,"Edit"))//得到edit子窗体句柄
        {
            ::SendMessage(hWnd,WM_SETTEXT,0,(LPARAM)mess);
            return 0;
        }
    }
    return true;
}

程序的功能是改写名为button.exe程序中内存地址为0x0040505d的值为97,即ASCII值的a,此处内存的原内容为ASCII值的m

被改动的程序实现代码例如以下:

#include <windows.h>
#include <stdio.h>
LRESULT CALLBACK _procWinMain(HWND,UINT,WPARAM,LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
    HWND hWinMain,hButton1,hButton2;
    MSG stMsg;
    WNDCLASSEX stWndClass;
    RtlZeroMemory(&stWndClass,sizeof(stWndClass));//WNDCLASSEX结构置零
    //注冊窗体类
    stWndClass.hCursor=::LoadCursor(0,IDC_ARROW);
    stWndClass.hInstance=hInstance;
    stWndClass.cbSize=sizeof(WNDCLASSEX);
    stWndClass.style=CS_HREDRAW||CS_VREDRAW;
    stWndClass.lpfnWndProc=_procWinMain;
    stWndClass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
    stWndClass.lpszClassName="myclass";
    ::RegisterClassEx(&stWndClass);
    //建立并显示窗体
    hWinMain=::CreateWindowEx(WS_EX_CLIENTEDGE,"myclass","firstwindow",WS_OVERLAPPEDWINDOW,100,100,600,400,NULL,NULL,hInstance,NULL);
    //建立button
    hButton1=::CreateWindowEx(NULL,"BUTTON","button1",WS_VISIBLE|WS_CHILD,300,200,60,20,hWinMain,(HMENU)1,hInstance,NULL);
    hButton2=::CreateWindowEx(NULL,"BUTTON","button2",WS_VISIBLE|WS_CHILD,100,200,60,20,hWinMain,(HMENU)2,hInstance,NULL);

    ::ShowWindow(hWinMain,SW_SHOWNORMAL);
    ::UpdateWindow(hWinMain);
    while(1)
    {
        if(::GetMessage(&stMsg,NULL,0,0)==0)//消息为WM_QUIT
            break;
        else
        {
            ::TranslateMessage(&stMsg);
            ::DispatchMessage(&stMsg);
        }
    }
    return 0;
}
LRESULT CALLBACK _procWinMain(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
    if(uMsg==WM_CLOSE)
    {
        ::DestroyWindow(hWnd);
    }
    else if(uMsg==WM_DESTROY)
    {
        ::PostQuitMessage(NULL);
    }
    else if(uMsg==WM_COMMAND)
    {
        char temp1[256],temp2[256];
        ::itoa((int)wParam,temp1,10);
        ::strcpy(temp2,"wParam: ");
        ::strcat(temp2,temp1);
        ::strcat(temp2," lParam: ");
        ::itoa((int)lParam,temp1,10);
        ::strcat(temp2,temp1);
        ::strcat(temp2," mess");
        ::MessageBox(NULL,temp2,"command",MB_OK);
    }
    else
    {
        return ::DefWindowProc(hWnd,uMsg,wParam,lParam);
    }
    return 0;
}

这个程序的功能是在窗体上建立两个button,点击不论什么一个button都会弹出一个对话框,输出button回调函数的wParam、lParam參数的值,外加一段字符串“mess”,我们要改动的就是字符串“mess”的第一个字符“m”为“a”。

将两端代码编译以后先打开button程序,点击窗体上的随意一个按钮,应该弹出例如以下的对话框

--------------------------------------------------------------------------------------华丽的切割线------------------------------------------------------------------------------

http://www.cppblog.com/windcsn/archive/2006/04/20/5981.html

这一篇主要讲了怎样使用消息进行进程间通信

近期在写个程序的时候须要在进程间通讯,详细需求是这样。

1.       主要有两个进程:一个进程作为被请求进程,我们称为 SERVER 进程;还有一个进程是请求进程,称为 CLIENG 进程。

2.       SERVER 进程提供一些服务,其完毕计算功能;而 CLIENT 进程须要在它运行完计算之后将结果取会。

因为计算结果可能是一个结构,也可能是一个复杂的数据,所以通过消息来在进程传递信息是有限的。还有一方面通常是单方向的通讯,实际上这里的需求有一个双向性,看下图:

这里两个进程都能够有自己的窗体,因此实际上我们能够通过消息来通知对方。但细致一想,请求服务通过windows消息是没有问题的,通知结果通过消息是不妥当的,实际上我们须要在请求服务完以后马上得到运行结果,而使用windows消息可能有时间上的问题,并且同步很麻烦。

想要的结果是在 CLIENT 请求服务以后马上得到返回结果,但我们能够改变一下思路就easy多了:结果不是有 SERVER 返回,而由 CLIENG 自己去获取。这样,我们能够在请求消息的时候使用 SendMessage 来发送这个请求。这是必须的, SendMessage 发送消息是同步的方式,必须等到消息处理完成之后才返回,而这正是我们想要的结果。那么 CLIENT 怎么样才干获得 SERVER 进程的结果来。

我们知道, WINDOWS 下每一个进程都有自己的地址空间,普通情况下一个进程訪问你一个进程的地址是不对的,最简单的是提示该地址无效,程序崩溃。当然还是有非常多中方式来读取对方进程的地址空间上的数据。

1.  能够做一个 DLL ,利用注入 DLL 的方式,来将该 DLL 注入到远程进程的地址空间上,然后通过 DLL 的 API 来读取。这个方式有点麻烦,还必须写一个 DLL ,还要注入 DLL 。

2.  使用 WriteProcessMemory 和 ReadProcessMemory 来读写远程进程的内存。这样的方式相对照较简单,其有一个參数远程进程的 HANDLE 指示你须要读写哪个进程的内存。当然,使用这两个函数是须要远程进程的地址空间的,这个地址是通过 VirtualAllocEx 来分配的,其通过 VirtualFreeEx 来释放。这两个 API 也有一个进程句柄參数。

有人问,为什么不使用 WM_COPYDATA 来传递大块数据?好,该消息是能够传递大块数据,但我们的应用中须要消息的双向,所以这里使用 WM_COPYDATA 是不合适的。

以下我们看一下第 2 种方法的详细步骤:

1.  找到对方进程的窗体。

2.  找到他的进程 ID

3.  使用 PROCESS_VM_OPERATION| PROCESS_VM_WRITE|PROCESS_VM_READ 标志来打开该进程,得到该继承的 HANDLE 。

4.  使用 VirtualAllocEx 来在该进程上分配适当大小的内存,得到一个地址,这个地址是远程进程的,通过不同的方式来改动该地址上的值是无效的。

5.  假设须要传递一些參数到远程进程,我们能够在该内存上写一些内容,通过 WriteProcessMemory 来完毕

6.  使用 SendMessage 来发送请求服务消息,同一时候将上面分配的内存地址作为參数传递给远程进程。

7.  远程进程得到指定消息后处理该消息,取得參数,计算结果,将结果写到指定的地址。因为这个地址是远程进程自己的地址空间,其操作这块内存的方法没有什么特别之处。

8.  SendMessage 消息返回, CLIENT 知道后,从上面的内存地址中读取返回结果;这里必须使用 ReadProcessMemory 来读取。好了,整个过程结束。

9.  调用 VritualFreeEx 将上面的内存释放。

这里须要强调两点:

1.  打开进程的时候必须设置对虚拟内存可操作、可写、可读,假设仅仅是可写,那么 ReadProcessMemory 将读取不对。

2.  必须释放该内存。

以下是部分程序:

CLIENT 程序:

#define     WM_COMPAREIMAGE WM_USER +100

void CTestCompareDlg::OnBnClickedButton1()

{

HANDLE hProcess = NULL;

DWORD dwProcessId = 0;

HWND hServerWnd = ::FindWindow(NULL,"CompareServer");

if(hServerWnd == NULL)

{

//Need create the process

return ;

}

::GetWindowThreadProcessId(hServerWnd,&dwProcessId);

hProcess = OpenProcess(PROCESS_VM_OPERATION|

PROCESS_VM_WRITE|PROCESS_VM_READ,FALSE,dwProcessId);

if(hProcess == NULL)
return ;

MyInfo * pMyInfo = NULL;

pMyInfo = (MyInfo *)VirtualAllocEx(hProcess,NULL,

sizeof(MyInfo),MEM_COMMIT,PAGE_READWRITE);

if(pMyInfo == NULL)
return ;

MyInfo myInfo;

myInfo.blue = 20.01;

myInfo.red = 3333;

WriteProcessMemory(hProcess,pMyInfo,&myInfo,sizeof(MyInfo),NULL);

::SendMessage(hServerWnd,WM_COMPAREIMAGE,sizeof(MyInfo),(LPARAM)pMyInfo);

DWORD dwRead = 0;

MyInfo myInfo2;

BOOL bRet = ::ReadProcessMemory(hProcess,pMyInfo,&myInfo2,sizeof(MyInfo),&dwRead);

dwRead = GetLastError();

m_log.Format("red =%.2f,blue=%.2f",myInfo2.blue,myInfo2.red);

TRACE(m_log);

VirtualFreeEx(hProcess,pMyInfo,0,MEM_RELEASE);

UpdateData(FALSE);

}

SERVER 程序:

LRESULT    CMyWindow::OnCompareImage(HWND hWnd,WPARAM wParam,LPARAM lParam)

{

if(wParam <sizeof(MyInfo))
return -1;

MyInfo * pMyInfo = (MyInfo *)lParam;

sprintf(m_strLog,"client:red=%.2f,blue=%.2f",pMyInfo->red,pMyInfo->blue);

::TextOut(GetDC(hWnd),0,50,m_strLog,strlen(m_strLog));

pMyInfo->blue = 1.0;

pMyInfo->red = 2.0;

return 0;

}

--------------------------------------------------------------------------------------华丽的切割线------------------------------------------------------------------------------

http://www.hackbase.com/tech/2012-05-30/66582.html

这一篇主要讲述了怎样创建远程线程, 实际上没有讲dll注入

所谓DLL注入就是将一个DLL放进某个进程的地址空间里,让它成为那个进程的一部分。要实现DLL注入,首先须要打开目标进程。

  hRemoteProcess = OpenProcess( PROCESS_CREATE_THREAD | //同意远程创建线程

  PROCESS_VM_OPERATION | //同意远程VM操作

  PROCESS_VM_WRITE, //同意远程VM写

  FALSE, dwRemoteProcessId )

  因为我们后面须要写入远程进程的内存地址空间并建立远程线程,所以须要申请足够的权限(PROCESS_CREATE_THREAD、VM_OPERATION、VM_WRITE)。

  假设进程打不开,以后的操作就别想了。进程打开后,就能够建立远线程了,只是别急,先想想这个远线程的线程函数是什么?我们的目的是注入一个DLL。并且我们知道用LoadLibrary能够载入一个DLL到本进程的地址空间。于是,自然会想到假设能够在目标进程中调用LoadLibrary,不就能够把DLL载入到目标进程的地址空间了吗?对!就是这样。远线程就在这儿用了一次,建立的远线程的线程函数就是LoadLibrary,而參数就是要注入的DLL的文件名称。(这里须要自己想一想,注意到了吗,线程函数ThreadProc和LoadLibrary函数很相似,返回值,參数个数都一样)
另一个问题,LoadLibrary这个函数的地址在哪儿?或许你会说,这个简单,GetProcAddress就能够得出。于是代码就出来了。

  char *pszLibFileRemote="my.dll";

  PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA");

  CreateRemoteThread( hRemoteProcess, NULL, 0, pfnStartAddr, pszLibFileRemote, 0, NULL);

  可是不正确!不要忘了,这是远线程,不是在你的进程里,而pszLibFileRemote指向的是你的进程里的数据,到了目标进程,这个指针都不知道指向哪儿去了,相同pfnStartAddr这个地址上的代码到了目标进程里也不知道是什么了,不知道是不是你想要的LoadLibraryA了。可是,问题总是能够解决的,Windows有些非常强大的API函数,他们能够在目标进程里分配内存,能够将你的进程中的数据复制到目标进程中。因此pszLibFileRemote的问题能够攻克了。

  char *pszLibFileName="my.dll";//注意,这个一定要是全路径文件名称,除非它在系统文件夹里;原因大家自己想想。

  //计算DLL路径名须要的内存空间

  int cb = (1 + lstrlenA(pszLibFileName)) * sizeof(char);

  //使用VirtualAllocEx函数在远程进程的内存地址空间分配DLL文件名称缓冲区

  pszLibFileRemote = (char *) VirtualAllocEx( hRemoteProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);

  //使用WriteProcessMemory函数将DLL的路径名拷贝到远程进程的内存空间

  iReturnCode = WriteProcessMemory(hRemoteProcess, pszLibFileRemote, (PVOID) pszLibFileName, cb, NULL);

  OK,如今目标进程也认识pszLibFileRemote了,可是pfnStartAddr好像不好办,我怎么可能知道LoadLibraryA在目标进程中的地址呢?事实上Windows为我们攻克了这个问题,LoadLibraryA这个函数是在Kernel32.dll这个核心DLL里的,而这个DLL非常特殊,无论对于哪个进程,Windows总是把它载入到同样的地址上去。因此你的进程中LoadLibraryA的地址和目标进程中LoadLibraryA的地址是同样的(事实上,这个DLL里的全部函数都是如此)。至此,DLL注入结束了。

[cpp]

/*

远程注入explorer.exe,不停Beep,注入完就退出。

*/

#include <windows.h>

#include <stdio.h>

#include <tlhelp32.h>

#include <Shlwapi.h>

#include <tchar.h>

#pragma comment(lib,"Shlwapi.lib")

#pragma comment(linker, "/BASE:0x14000000")

//#define NoWindow

#ifdef NoWindow

#pragma comment(linker,"/subsystem:windows /FILEALIGN:0x200 /ENTRY:main")

#pragma comment(linker,"/INCREMENTAL:NO /IGNORE:4078")

#pragma comment(linker,"/MERGE:.idata=.text /MERGE:.data=.text /MERGE:.rdata=.text /MERGE:.text=Anskya /SECTION:Anskya,EWR")

#endif

typedef int (__stdcall *fnMessageBoxA)(HWND, LPCSTR, LPCSTR, UINT);

typedef int (__stdcall *fnBeep)(int,int);

#define ProcessName "services.exe"//"rundll32.exe"//"svchost.exe"//"explorer.exe"//"avp.exe"//"lsass.exe"//

//

//依据进程名,获得进程ID

DWORD GetProcessID(char *FileName)

{

HANDLE hProcess;

PROCESSENTRY32 pe;

BOOL bRet;

//进行进程快照

hProcess=::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);

//開始进程查找

bRet=::Process32First(hProcess,&pe);

//循环比較,得出ProcessID

while(bRet)

{

if(strcmp(FileName,pe.szExeFile)==0)

return pe.th32ProcessID;

else

bRet=::Process32Next(hProcess,&pe);

}

//返回得到的ProcessID

//  printf("Process not found!\n");

return 9999;

}

//

//远程注入函数 www.2cto.com

void __stdcall RmoteThread()

{

HMODULE hMod,hMod2;

fnMessageBoxA myMessageBoxA;

fnBeep myBeep;

char* path[MAX_PATH];

hMod = GetModuleHandle("user32.dll");

hMod2 = GetModuleHandle("kernel32.dll");

myMessageBoxA = (fnMessageBoxA)GetProcAddress(hMod, (LPCSTR)"MessageBoxA");

myBeep = (fnBeep)GetProcAddress(hMod2, (LPCSTR)"Beep");

/*for(int i=0;i<30;i++)

{

myBeep(800,400);

}

*/

//   while(1)

for(int i=0;i<6;i++)

{

Beep(600,100);

Sleep(200);

}

GetModuleFileName(NULL,(char*)path,MAX_PATH);

//   myMessageBoxA(NULL, (char*)path, NULL, 64);

}

//

// 提升应用级调试权限

BOOL EnablePrivilege(HANDLE hToken,LPCTSTR szPrivName,BOOL fEnable)

{

TOKEN_PRIVILEGES tp;

tp.PrivilegeCount = 1;

LookupPrivilegeValue(NULL,szPrivName,&tp.Privileges[0].Luid);

tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED:0;

AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(tp),NULL,NULL);

return((GetLastError() == ERROR_SUCCESS));

}

//

///说明: 插入代码,远程线程为RmoteThread()

///參数: Pid = 进程PID

///返回: 成功True,否则False

bool InjectExe(DWORD Pid)

{

bool       status = false;

LPVOID     pBaseAddr = NULL;

HMODULE    hMod = GetModuleHandle(NULL);

LONG       hNHOffset = PIMAGE_DOS_HEADER(hMod)->e_lfanew;

HANDLE     hThread,

hProcess,

hToken;

DWORD      cbImage;

//cbImage=内存中整个PE映像体的尺寸

cbImage= PIMAGE_NT_HEADERS((DWORD)hMod + (DWORD)hNHOffset)->OptionalHeader.SizeOfImage;

//重要,否则不能注入lsass

OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken);

EnablePrivilege(hToken,SE_DEBUG_NAME,TRUE);

hProcess  = OpenProcess(PROCESS_ALL_ACCESS, TRUE, Pid);

if (hProcess == NULL)

{

#ifdef debug

MessageBoxA(NULL, "错误OpenProcess", NULL, 64);

#endif

goto Err;

}

//释放远程内存

VirtualFreeEx(hProcess, LPVOID(hMod), 0, MEM_RELEASE);

//分配远程内存

pBaseAddr = VirtualAllocEx(hProcess, LPVOID(hMod), cbImage, MEM_COMMIT | MEM_RESERVE,

PAGE_EXECUTE_READWRITE);

if (pBaseAddr == NULL)

{

#ifdef debug

MessageBoxA(NULL, "VirtualAllocEx failed", NULL, 64);

#endif

goto Err;

}

//写进去,将本进程的整个PE体 全写进目标进程,够狠~

if (!WriteProcessMemory(hProcess, pBaseAddr, LPVOID(hMod), cbImage, NULL))

{

#ifdef debug

MessageBoxA(NULL, "WriteProcessMemory failed", NULL, 64);

#endif

goto Err;

}

hThread = CreateRemoteThread(hProcess, NULL, NULL, \

(LPTHREAD_START_ROUTINE)&RmoteThread, NULL, NULL, NULL);

if (hThread == NULL)

{

#ifdef debug

MessageBoxA(NULL, "CreateRemoteThread failed", NULL, 64);

#endif

goto Err;

}

//   WaitForSingleObject(hThread, INFINITE);

CloseHandle(hThread);

CloseHandle(hProcess);

status = TRUE;

return status; //自己返回即可,不要VirtualFreeEx;,否则宿主就挂了!

Err:

if (pBaseAddr != NULL)

VirtualFreeEx(hProcess, pBaseAddr, 0, MEM_RELEASE);

if (hProcess != NULL)

CloseHandle(hProcess);

return status;

}

//

int main()

{

char aa[]="aBcDdddFFFF asfd";

strupr((char*)aa);

printf(aa);

if (!InjectExe(GetProcessID(ProcessName)))

Beep(1800,500);

return 0;

}

时间: 2024-10-13 09:14:57

通过WriteProcessMemory改写进程的内存的相关文章

[转]观察进程的内存占用情况

转:http://www.cnblogs.com/bravery/archive/2012/06/27/2560611.html 概述 想必在linux上写过程序的同学都有分析进程占用多少内存的经历,或者被问到这样的问题--你的程序在运行时占用了多少内存(物理内存)?通常我们可以通过top命令查看进程占用了多少内存.这里我们可以看到VIRT.RES和SHR三个重要的指标,他们分别代表什么意思呢?这是本文需要跟大家一起探讨的问题.当然如果更加深入一点,你可能会问进程所占用的那些物理内存都用在了哪些

强制读写进程的内存

某些时候我们需要读写别的进程的内存,某些时候别的进程已经对自己的内存读写做了保护,这里说四个思路(两个R3的,两个R0的). 方案1(R3):直接修改别人内存 最基本的也最简单的就是直接通过WriteProcessMemory 和 ReadProcessMemory对没有进行保护的程序的内存进行修改,一些单机游戏辅助什么的可能会有这种简单方式修改其他进程内存. 方案2(R3): 注入 通过注入的方式想办法进入宿主进程,然后修改他的内存.这里的话姿势就很多了,远程代码注入,APC注入,输入法注入,

如何分析进程的内存占用问题

一共推荐三种分析内存占用的方式 1.vmmap.exe 属于SysinternalsSuite中的工具,很强大,可以方便的查看特定进程的内存总大小(Size).内存的提交大小(Committed).内存专用工作集等(Private WS)等,也可以启动一个进程定时生成快照. 具体各名词介绍可以参考工具的help,或者参考如下文章: vmmap介绍与下载地址:https://technet.microsoft.com/en-us/sysinternals/vmmap vmmap用法介绍:http:

UNIX高级环境编程(15)进程和内存分配 &lt; 故宫角楼 &gt;

故宫角楼是很多摄影爱好者常去的地方,夕阳余辉下的故宫角楼平静而安详. ? 首先,了解一下进程的基本概念,进程在内存中布局和内容. 此外,还需要知道运行时是如何为动态数据结构(如链表和二叉树)分配额外内存的. 一 进程 1 进程和程序 进程:是一个可执行程序的实例. 程序:包含一系列信息的文件,这些信息描述了如何在运行时创建一个进程.包含如下信息: 二进制格式标识:如最常见的ELF格式. 机器语言指令:对程序算法进行编码. 程序入口地址:标识程序开始执行时的起始指令位置. 数据:程序文件包含的变量

波波讲堂2-(进程,内存等等)

1.ps -ef| grep XXXXXX进程号 ls -l /proc/$PID/exe 哪个脚本产生的进程ls -l /proc/$PID/cwd 进程所运行的目录 2.ps 命令参数 -e 显示所有进程 -f 显示完整的格式列表 3.top命令 %CPU 进程正使用的CPU时间份额 %MEM 进程正使用的物理内存份额 4.vmstat 查看内存 5.df -h 6.du -sh 7.sort 文件名 按行,首字母排序 8.sort -n 文件名 将数字大小排序,从小到大 如果有字母,字母在

Linux中查看进程占用内存和系统资源情况的命令

用 'top -i' 看看有多少进程处于 Running 状态,可能系统存在内存或 I/O 瓶颈,用 free 看看系统内存使用情况,swap 是否被占用很多,用 iostat 看看 I/O 负载情况... 还有一种办法是 ps -ef | sort -k7 ,将进程按运行时间排序,看哪个进程消耗的cpu时间最多. top: 主要参数 d:指定更新的间隔,以秒计算. q:没有任何延迟的更新.如果使用者有超级用户,则top命令将会以最高的优先序执行. c:显示进程完整的路径与名称. S:累积模式,

linux下对进程按照内存使用情况进行排序

linux下对进程按照内存使用情况进行排序的命令为:ps aux --sort -rss 详细解说参见 http://alvinalexander.com/linux/unix-linux-process-memory-sort-ps-command-cpu

多个进程共享内存

HANDLE hmapfile = OpenFileMapppingA(FILE_MAP_READ, FALSE, "shijiaxing");    //打开共享内存,可以用于进程通信,也可以用于线程通行.第一个参数是首地址第二个参数表示是否将其锁定为当前的进程内,FALSE表示不锁定.第三个是命名. 在操作系统中,一个进程是不能读写另一个进程的内存的,他们的进程内存必须是互相独立的,C语言把所有的设备都当作文件来处理,在内存里开辟了一段数据,开辟了一段缓冲区,把他模拟成设备,两个进

进程的内存空间布局

进程的内存布局在结构上是有规律的,具体来说对于 linux 系统上的进程,其内存空间一般可以粗略地分为以下几大段[1],从高内存到低内存排列: 1.内核态内存空间,其大小一般比较固定(可以编译时调整),但 32 位系统和 64 位系统的值不一样. 2.用户态的堆栈,大小不固定,可以用 ulimit -s 进行调整,默认一般为 8M,从高地址向低地址增长. 3.mmap 区域,进程茫茫内存空间里的主要部分,既可以从高地址到低地址延伸(所谓 flexible layout),也可以从低到高延伸(所谓