我需要一种方法来限制服务可能分配的内存量,以防止服务饿死系统,类似于SQL Server允许您设置“最大服务器内存”的方式。
我知道SetProcessWorkingSetSize并不完全符合我的要求,但是我试图让它以我相信它应该的方式行事。 无论我使用的是什么值,我的testing应用程序的工作集不受限制。 此外,如果之后立即调用GetProcessWorkingSetSize,则返回的值不是我之前指定的值。 这里是我的testing应用程序使用的代码:
var MinWorkingSet: SIZE_T; MaxWorkingSet: SIZE_T; begin if not SetProcessWorkingSetSize(GetCurrentProcess(), 20, 12800 ) then RaiseLastOSError(); if GetProcessWorkingSetSize(GetCurrentProcess(), MinWorkingSet, MaxWorkingSet) then ShowMessage(Format('%d'#13#10'%d', [MinWorkingSet, MaxWorkingSet]));
没有错误发生,但GetProcessWorkingSetSize返回的最小值和最大值都是81,920。
我试着在Flags参数中使用SetProcessWorkingSetSizeEx使用QUOTA_LIMITS_HARDWS_MAX_ENABLE($ 00000004)。 不幸的是,SetProcessWorkingSetSizeEx失败,代码87.参数不正确“,如果我在标志中传递除$ 00000000以外的任何东西。
我也追求使用Job Objects来实现相同的目标。 当启动subprocess时,我有内存限制使用作业对象。 但是,我需要一种服务来设置自己的内存限制,而不是依赖于“启动”服务。 到目前为止,我还没有find一种方法让单个进程创build一个作业对象,然后将其自身添加到作业对象中。 访问被拒绝时,这总是失败。
任何想法或build议?
SetProcessWorkingSetSize
函数的文档说:
dwMinimumWorkingSetSize [in]
…
该参数必须大于零但小于或等于最大工作集大小。 默认大小是50页(例如,在具有4K页面大小的系统上,这是204,800字节)。 如果该值大于零但小于20页,则最小值设置为20页。
在4K页面大小的情况下,强加的最小值是20 * 4096 = 81920字节,这是您看到的值。 这些值以字节为单位指定。
为了实际限制服务进程的内存,我认为可以创建一个新的工作( CreateJobObject
),设置内存限制( SetInformationJobObject
),并将当前进程分配给服务启动例程中的作业( AssignProcessToJobObject
)。
不幸的是,在Windows 8和server 2012之前的Windows中,如果进程已经属于某个作业,这将不起作用:
Windows 7,Windows server 2008 R2,带有SP3,Windows server 2008,Windows Vista和Windows server 2003的Windows XP:该流程不得已分配给作业; 如果是,则该函数将以ERROR_ACCESS_DENIED失败。 此行为从Windows 8和Windows server 2012开始更改。
如果是这种情况(例如,在较旧的Windows上得到ERROR_ACCESS_DENIED
),请检查进程是否已分配给作业(在这种情况下,您运气不佳),但也要确保它具有所需的访问权限: PROCESS_SET_QUOTA
和PROCESS_TERMINATE
。