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;    

}

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

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

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

  2. HBase 学习笔记---守护进程及内存调优

    1.HMaster           HMaster的任务前面已经说过了,两个大方向:一.管理Hbase Table的 DDL操作 二.region的分配工作,任务不是很艰巨,但是如果采用默认自动s ...

  3. 进程与线程(二) java进程的内存模型

    从我出生那天起,我就知道我有个兄弟,他桀骜不驯,但实力强悍 ,人家都叫它C+++            ----java 上回说到了,C进程的内存分配,那么一个java运行过程也是一个进程,java内 ...

  4. .NET(C#):获取进程的内存私有工作集

    当前.NET Framework(.NET 4.0)的Process仅提供进程的内存工作集的获取(通过WorkingSet64属性),而没有提供对私有工作集的获取.注意在Windows Vista之后 ...

  5. Windows中进程的内存结构

    基础知识: 栈是一种简单的数据结构,是一种只允许在其一端进行插入或删除的线性表.允许插入或删除操作的一端称为栈顶,另一端称为栈底,对栈的插入和删除操作被称为入栈和出栈. 有一组CPU指令可以实现对进程 ...

  6. Android进程的内存管理分析

    尊重原创作者,转载请注明出处: http://blog.csdn.net/gemmem/article/details/8920039 最近在网上看了不少Android内存管理方面的博文,但是文章大多 ...

  7. Linux进程分配内存的两种方式--brk() 和mmap()

    如何查看进程发生缺页中断的次数? 用ps -o majflt,minflt -C program命令查看. majflt代表major fault,中文名叫大错误,minflt代表minor faul ...

  8. 内存分配的原理__进程分配内存有两种方式,分别由两个系统调用完成:brk和mmap(不考虑共享内存)

    如何查看进程发生缺页中断的次数? 用ps -o majflt,minflt -C program命令查看. majflt代表major fault,中文名叫大错误,minflt代表minor faul ...

  9. Linux 查看进程消耗内存情况总结

    在Linux中,有很多命令或工具查看内存使用情况,今天我们来看看如何查看进程消耗.占用的内存情况,Linux的内存管理和相关概念要比Windows复杂一些.在此之前,我们需要了解一下Linux系统下面 ...

随机推荐

  1. quick-x 触摸事件的新方法

    --[[ local function onTouch(event, x, y) print(event, x, y) if event == "began" then retur ...

  2. "Cannot convert value '0000-00-00' from column 2 to TIMESTAMP"mysql时间转换bug

    今天在项目中遇到这样的一个bug,Cannot convert value '0000-00-00' from column 2 to TIMESTAMP 仔细一查,经过http://blog.csd ...

  3. 使用spring的jdbcTemplate-----用JDBC模板查询数据库

    JdbcTemplate类声明了几个重载的query()模板方法来控制整个查询过程,就像进行更新数据操作一样,通过实现PreparedStatementCreator和PreparedStatemen ...

  4. 流的概念(来自MSDN)

    本文来源 定义 提供字节序列的一般视图.Provides a generic view of a sequence of bytes. 流涉及三个基本操作 Streams involve three ...

  5. Watch gcc at ubuntu 12,See ELF file header

    first write article at my ubuntu 12. ELF is very important file format.

  6. lc面试准备:Remove Duplicates from Sorted List

    1 题目 Given a sorted linked list, delete all duplicates such that each element appear only once. For ...

  7. 【HDOJ】1930 And Now, a Remainder from Our Sponsor

    简单字符串. #include <stdio.h> #define MAXLEN 160 char buf[MAXLEN]; ], parts[]; void getpart(int x) ...

  8. bzoj1306

    非常好的一道搜索题首先没有别的好办法就只能搜,基于对称性我只要搜对角线上半部分即可然后有些惯用的剪枝啦什么的,具体见程序然后代码很短,然后TLE了(但好像也有人过了)然后就不知道怎么优化了,看到CLJ ...

  9. BZOJ3039: 玉蟾宫&wikioi2491 玉蟾宫

    3039: 玉蟾宫 Time Limit: 2 Sec  Memory Limit: 128 MBSubmit: 430  Solved: 265[Submit][Status] Descriptio ...

  10. BZOJ3036: 绿豆蛙的归宿&Wikioi2488:绿豆蛙的归宿

    3036: 绿豆蛙的归宿 Time Limit: 2 Sec  Memory Limit: 128 MBSubmit: 108  Solved: 73[Submit][Status] Descript ...