Job Object对进程的资源消耗的限制

wj_fantasy 2009-02-18 05:48:26
想限制一个c/c++实现的进程的时间和内存,比如要求一个即将被运行的进程运行时间不得超过1s,占用内存不得高于500K。
因为我想做的系统的前端是java,而Java又好像达不到这个目标。所以用了JNI。
最终的实现效果是,限制都已经设上去了,但运行的进程不管怎样都会一直运行到结束为止
不知道是什么原因,大家看看。
或者给个别的实现方法。

以下代码是在vc6上写的,生成一个dll,由java调用:

#define _WIN32_WINNT 0x0500
#include "ReturnInts.h"
#include <Windows.h>
#include <string.h>
#include <Psapi.h>
#include <Winbase.h>

#define KBITS 1024
#define MSEC 10000

void setLimits(HANDLE hJob,int s,int k)//set limits on job
{
//JOBOBJECT_BASIC_LIMIT_INFORMATION basic_limit = {0};
JOBOBJECT_EXTENDED_LIMIT_INFORMATION extended_limit = {0};


//basic_limit.PerProcessUserTimeLimit.QuadPart = 5*sec;
extended_limit.BasicLimitInformation.PerProcessUserTimeLimit.QuadPart = s*MSEC;//set time limit
extended_limit.ProcessMemoryLimit = k*KBITS;//set memory linmit
extended_limit.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_TIME | JOB_OBJECT_LIMIT_PROCESS_MEMORY ;

if(!SetInformationJobObject(
hJob, // handle to job
JobObjectExtendedLimitInformation, // information class
&extended_limit, // limit information
sizeof(extended_limit) // size of limit information
))
{
printf("SetInformationJobObject fail!\n");
}

}

void queryLimits(HANDLE hJob)//query limist set on job
{
JOBOBJECT_EXTENDED_LIMIT_INFORMATION extended_limit = {0};
DWORD cb = 0;
QueryInformationJobObject(
hJob, // handle to job
JobObjectExtendedLimitInformation, // information class
&extended_limit, // limit information
sizeof(extended_limit), // limit information size
&cb // data written
);
if(cb == 0)
printf("no date!\n");
else{
printf("\ntime limit = %d\n",extended_limit.BasicLimitInformation.PerProcessUserTimeLimit.QuadPart);
printf("memory limit = %d\n",extended_limit.ProcessMemoryLimit);
}

}




JNIEXPORT jintArray JNICALL Java_ReturnInts_retInts
(JNIEnv *env, jclass cl, jstring str)
{
jint ntvRet[3] = {1,2,3};
jintArray ret = env->NewIntArray(3);
env->SetIntArrayRegion(ret, 0, 3, ntvRet);
return ret;
}

JNIEXPORT jint JNICALL Java_ReturnInts_runApp
(JNIEnv *env, jclass cl, jstring file)
{
STARTUPINFO si = {sizeof(si)};
PROCESS_INFORMATION pi;
char szCmdLine[128]={0};
const char* CmdLine = env->GetStringUTFChars(file,0);
strcpy(szCmdLine,CmdLine);
env->ReleaseStringUTFChars(file,CmdLine);
if( !CreateProcess( NULL, // No module name (use command line).
szCmdLine,
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
CREATE_SUSPENDED, //creation flags.
NULL, // Use parent's environment block.
NULL, // Use parent's starting directory.
&si, // Pointer to STARTUPINFO structure.
&pi ) // Pointer to PROCESS_INFORMATION structure.
)
{
printf( "CreateProcess failed." );
return 0;
}


printf("run the process...\n");
ResumeThread(pi.hThread);
CloseHandle(pi.hThread);

WaitForSingleObject( pi.hProcess, INFINITE );

PROCESS_MEMORY_COUNTERS pmc = {0};
GetProcessMemoryInfo(pi.hProcess,&pmc,sizeof(pmc));
printf("\nPeakWorkingSetSize=%dk\n",pmc.PeakWorkingSetSize/1024);

FILETIME CreateTime,ExitTime,KernelTime,UserTime;
GetProcessTimes(pi.hProcess,&CreateTime,&ExitTime,&KernelTime,&UserTime);
printf("UserTimeH=%ums,UserTimeL=%ums\n",UserTime.dwHighDateTime,UserTime.dwLowDateTime);
printf("KernelTime=%ums\n",KernelTime.dwLowDateTime);
printf("diffTime=%u\n",ExitTime.dwLowDateTime-CreateTime.dwLowDateTime);

DWORD cb;
GetExitCodeProcess(pi.hProcess,&cb);

CloseHandle(pi.hProcess);
return cb;
}


JNIEXPORT jintArray JNICALL Java_ReturnInts_RunAppInJob
(JNIEnv *env, jclass cl, jint tLimit, jint mLimit, jstring file)
{
jint ntvRet[3] = {-1,-2,-3};
jintArray ret = env->NewIntArray(3);
env->SetIntArrayRegion(ret, 0, 3, ntvRet);

HANDLE hjob = CreateJobObject(NULL,NULL);//创建JOB对象
setLimits(hjob,tLimit,mLimit);//设置时间和内存的限制
queryLimits(hjob);//调试用的,看看是否添加限制成功

STARTUPINFO si = {sizeof(si)};
PROCESS_INFORMATION pi;
char szCmdLine[128]={0};
const char* CmdLine = env->GetStringUTFChars(file,0);
strcpy(szCmdLine,CmdLine);
env->ReleaseStringUTFChars(file,CmdLine);
//创建进程
if( !CreateProcess( NULL, // No module name (use command line).
szCmdLine,
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
CREATE_SUSPENDED, //creation flags.
NULL, // Use parent's environment block.
NULL, // Use parent's starting directory.
&si, // Pointer to STARTUPINFO structure.
&pi ) // Pointer to PROCESS_INFORMATION structure.
)
{
// printf( "CreateProcess failed." );
return ret;
}


// printf("run the process...\n");
ResumeThread(pi.hThread);
CloseHandle(pi.hThread);

WaitForSingleObject( pi.hProcess, INFINITE );
//下面部分是当进程结束后查询进程消耗的资源 PROCESS_MEMORY_COUNTERS pmc = {0};
GetProcessMemoryInfo(pi.hProcess,&pmc,sizeof(pmc));
printf("\nPeakWorkingSetSize=%dk\n",pmc.PeakWorkingSetSize/1024);

ntvRet[1] = pmc.PeakWorkingSetSize/1024;

FILETIME CreateTime,ExitTime,KernelTime,UserTime;
GetProcessTimes(pi.hProcess,&CreateTime,&ExitTime,&KernelTime,&UserTime);
printf("UserTimeH=%ums,UserTimeL=%ums\n",UserTime.dwHighDateTime,UserTime.dwLowDateTime);
printf("KernelTime=%ums\n",KernelTime.dwLowDateTime);
printf("diffTime=%u\n",ExitTime.dwLowDateTime-CreateTime.dwLowDateTime);

ntvRet[2] = ExitTime.dwLowDateTime-CreateTime.dwLowDateTime;

DWORD cb;
GetExitCodeProcess(pi.hProcess,&cb);

ntvRet[0] = cb;

env->SetIntArrayRegion(ret, 0, 3, ntvRet);

CloseHandle(pi.hProcess);
CloseHandle(hjob);
return ret;
}





















...全文
388 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
luyikk 2009-11-01
  • 打赏
  • 举报
回复
哥来教你用

// 传说中的作业.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "Windows.h"
#include "strsafe.h"

#define sec 10

void StartRestrictedProcess()
{
BOOL bInJob=FALSE;

IsProcessInJob(GetCurrentProcess(),NULL,&bInJob);

if(bInJob)
{
MessageBox(NULL,_T("你的进程已经有作业了哦 请用CMD运行此程序哦"),_T(""),0);
return;
}

::HANDLE hjob=::CreateJobObject(NULL,_T("我的作业"));

::JOBOBJECT_BASIC_LIMIT_INFORMATION jobli={0};

jobli.PriorityClass=IDLE_PRIORITY_CLASS;
jobli.PerJobUserTimeLimit.QuadPart= sec*1000*10000;
jobli.LimitFlags=JOB_OBJECT_LIMIT_PRIORITY_CLASS|JOB_OBJECT_LIMIT_JOB_TIME;

::SetInformationJobObject(hjob,::JobObjectBasicLimitInformation,&jobli,sizeof(jobli));



::JOBOBJECT_BASIC_UI_RESTRICTIONS jobuir;
jobuir.UIRestrictionsClass=JOB_OBJECT_UILIMIT_NONE;
jobuir.UIRestrictionsClass|=JOB_OBJECT_UILIMIT_EXITWINDOWS;
jobuir.UIRestrictionsClass|=JOB_OBJECT_UILIMIT_HANDLES;
::SetInformationJobObject(hjob,::JobObjectBasicUIRestrictions,&jobuir,sizeof(jobuir));


::STARTUPINFO si={sizeof(STARTUPINFO)};

::PROCESS_INFORMATION pi;

TCHAR CmdLine[MAX_PATH];

::_tcscpy_s(CmdLine,_countof(CmdLine),_T("test.exe"));

BOOL bResult=::CreateProcess(NULL,CmdLine,NULL,NULL,FALSE,CREATE_SUSPENDED|CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi);

::AssignProcessToJobObject(hjob,pi.hProcess);


ResumeThread(pi.hThread);

CloseHandle(pi.hThread);

::HANDLE h[2];

h[0]=pi.hProcess;
h[1]=hjob;

DWORD dw=::WaitForMultipleObjects(2,h,FALSE,INFINITE);


switch(dw-WAIT_OBJECT_0)
{
case 0:
break;
case 1:
break;

}


::FILETIME CreationTime;
::FILETIME ExitTime;
::FILETIME KernelTime;
::FILETIME UserTime;

TCHAR szInfo[MAX_PATH];

::GetProcessTimes(pi.hProcess,&CreationTime,&ExitTime,&KernelTime,&UserTime);


::StringCchPrintf(szInfo,_countof(szInfo),_T("Kernel=%u | User=%u\n"),KernelTime.dwLowDateTime/10000,UserTime.dwLowDateTime/10000);

::MessageBox(::GetActiveWindow(),szInfo,TEXT("Restricted Process times"),0);

::CloseHandle(pi.hProcess);
::CloseHandle(hjob);










}


int _tmain(int argc, _TCHAR* argv[])
{
StartRestrictedProcess();
return 0;
}

baozi999 2009-09-20
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 virghost 的回复:]
得分回复需要阅读,请登录CSDN!
[/Quote]

这个我在vs2008里也不好使啊。谁给点建议!!
VirGhost 2009-02-18
  • 打赏
  • 举报
回复
汗,我还一直怕自己看漏了呢...
wj_fantasy 2009-02-18
  • 打赏
  • 举报
回复
我说呢,vs2008里的还能行的。。。。。
这个代码里没放进去,呵呵~~谢谢楼上的了~~~
有时候自己怎么都看不出来,当局者迷啊~~~

VirGhost 2009-02-18
  • 打赏
  • 举报
回复
试问一下,LZ有没有将新创建的Process加入Job
wj_fantasy 2009-02-18
  • 打赏
  • 举报
回复
也在vs2008上就纯粹的CPP写过差不多的代码,
那个代码的效果的是,超时的时候会结束进程,进程的结束代码为1816;
但,要是进程所需的内存远大于限制时,会弹出一个对话框,说初始话失败。。。。

3,881

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧