我需要一种方法来限制服务可以分配的内存量,以防止服务使系统挨饿,类似于SQL Server允许您设置"最大服务器内存的方式"。
我知道SetProcessWorkingSetSize并没有完全符合我的要求,但我试图让它按照我认为的方式行事。无论我使用什么值,我的测试应用程序的工作集都不受限制。此外,如果我之后立即调用GetProcessWorkingSetSize,则返回的值不是我之前指定的值。这是我的测试应用使用的代码:
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返回的Min和Max值都是81,920。
我尝试在Flags参数中使用QUOTA_LIMITS_HARDWS_MAX_ENABLE($ 00000004)使用SetProcessWorkingSetSizeEx。不幸的是,SetProcessWorkingSetSizeEx失败了"代码87.参数不正确"如果我在Flags中传递除$ 00000000以外的任何东西。
我也一直在使用Job Objects来实现相同的目标。启动子进程时,我有使用Job Objects的内存限制。但是,我需要服务能够设置自己的内存限制,而不是依赖于"启动"服务去做。到目前为止,我还没有找到一种方法来让单个进程创建一个作业对象,然后将自己添加到作业对象中。这总是因访问被拒绝而失败。
有任何想法或建议吗?
答案 0 :(得分:3)
SetProcessWorkingSetSize
函数的文档说:
dwMinimumWorkingSetSize [in]
...
此参数必须大于 零但小于或等于最大工作集大小。该 默认大小为50页(例如,这是204,800字节 具有4K页面大小的系统)。如果该值大于零但是 少于20页,最小值设置为20页。
如果是4K页面大小,则强加的最小值为20 * 4096 = 81920字节,这是您看到的值。 值以字节为单位指定。
要实际限制服务进程的内存,我认为可以创建一个新作业(CreateJobObject
),设置内存限制(SetInformationJobObject
)并将当前进程分配给作业( AssignProcessToJobObject
)在服务的启动例程中。
不幸的是,在8之前的Windows和Server 2012上,如果进程已经属于某个作业,这将不起作用:
Windows 7,Windows Server 2008 R2,带有SP3的Windows XP,Windows Server 2008,Windows Vista和Windows Server 2003:该过程绝对不能 已被分配到工作;如果是,则该功能失败 ERROR_ACCESS_DENIED。从Windows 8和Windows开始,此行为已更改 Windows Server 2012。
如果是这种情况(即你在旧版Windows上获得ERROR_ACCESS_DENIED
),请检查该进程是否已分配给某个作业(在这种情况下,你运气不好)但也要确保它拥有所需的访问权限:PROCESS_SET_QUOTA
和PROCESS_TERMINATE
。