.net 如何提高进程的 I/O 优先级?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/301290/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 10:38:54  来源:igfitidea点击:

How can I/O priority of a process be increased?

.netfile-iowindows-vista

提问by yusuf

I want to increase the I/O priority of a process. Answers for both .NET and Windows Vista would be nice. processexplorer is ok as well.

我想增加进程的 I/O 优先级。.NET 和 Windows Vista 的答案都很好。processexplorer 也可以。

回答by 1800 INFORMATION

The relevant information seems to be a bit scattered compared to the usual MS documentation. There is this white paper that discusses I/O Prioritization in windows. This doc seems to have beta flags all over it but I guess it's probably mostly pretty accurate.

与通常的 MS 文档相比,相关信息似乎有点分散。有这个白皮书讨论了 Windows 中的 I/O 优先级。该文档似乎到处都是测试版标志,但我想它可能大部分都非常准确。

Two important things to note:

需要注意的两个重要事项:

  1. You can only reduce the priority of IO requests below normal.
  2. The driver can ignore any such request and treat it as normal anyway.
  1. 您只能将 IO 请求的优先级降低到低于正常值。
  2. 驱动程序可以忽略任何此类请求并将其视为正常。

The useful APIs for client applications are SetFileInformationByHandle:

客户端应用程序的有用 API 是SetFileInformationByHandle

FILE_IO_PRIORITY_HINT_INFO priorityHint;
priorityHint.PriorityHint = IoPriorityHintLow;
result = SetFileInformationByHandle( hFile,
                                     FileIoPriorityHintInfo,
                                     &priorityHint,
                                     sizeof(PriorityHint));

SetPriorityClass:

设置优先级

// reduce CPU, page and IO priority for the whole process
result = SetPriorityClass( GetCurrentProcess(),
                           PROCESS_MODE_BACKGROUND_BEGIN);
// do stuff
result = SetPriorityClass( GetCurrentProcess(),
                           PROCESS_MODE_BACKGROUND_END);

SetThreadPrioritywhich is similar:

SetThreadPriority类似:

// reduce CPU, page and IO priority for the current thread
SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_BEGIN);
// do stuff
SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_END);

SetFileBandwithReservation:

SetFileBandwithReservation:

// reserve bandwidth of 200 bytes/sec
result = SetFileBandwidthReservation( hFile,
                                  1000,
                                  200,
                                  FALSE,
                                  &transferSize,
                                  &outstandingRequests );

For .Net do the usual stuff with P/Invoke.

对于 .Net,用 P/Invoke 做通常的事情。

回答by Charlie

It looks like the "real" way to set the IO priority of a process is using NtSetInformationProcesswith the ProcessIoPriorityinformation class. Unfortunately this API is undocumented, but you can see it in action by attaching a debugger to taskeng.exe and breaking in ExeTask::GetYourPrioritiesStraight.

看起来设置进程的 IO 优先级的“真正”方法是NtSetInformationProcessProcessIoPriority信息类一起使用。不幸的是,此 API 未记录在案,但您可以通过将调试器附加到 taskeng.exe 并插入ExeTask::GetYourPrioritiesStraight.

I believe the PROCESS_INFORMATION_CLASSvalue for ProcessIoPriorityis 33 (0x21), and the priority values are as follows:

我相信PROCESS_INFORMATION_CLASSfor的ProcessIoPriority值为33(0x21),优先级值如下:

Very Low: 0
Low: 1
Normal: 2
High: 3 or above?

The values above are a best-guess based on what I can tell from the debugger; the task scheduler seems to use a value of 1 for tasks with priority 7, and a value of 2 for tasks with priority 5 (see this questionand this MSDN articlefor more on task scheduler priorities). Calling SetPriorityClasswith PROCESS_MODE_BACKGROUND_BEGINuses a value of 0.

上面的值是根据我从调试器中得到的信息做出的最佳猜测;任务调度程序似乎对优先级为 7 的任务使用值 1,对优先级为 5 的任务使用值 2(有关任务调度程序优先级的更多信息,请参阅此问题此 MSDN 文章)。调用SetPriorityClasswithPROCESS_MODE_BACKGROUND_BEGIN使用值 0。

I have unfortunately not found any public API that can be used for this, other than the SetPriorityClassmethod in @1800 INFORMATION's answer, which sets the priority to Very Low.

不幸的是,除了SetPriorityClass@1800 INFORMATION 的答案中将优先级设置为“非常低”的方法之外,我还没有找到任何可用于此目的的公共 API 。

Edit: I've written a utility that can be used to query or set the IO prority of a process, available here.

编辑:我编写了一个实用程序,可用于查询或设置进程的 IO 优先级,可在此处获得

回答by dyasta

The proper way to do this is to call SetProcessPriorityClasswith PROCESS_BACKGROUND_MODE_BEGINto initiate a background mode. This causes a Very Low (background) I/O priority and Idle CPU priority. When done, call SetProcessPriorityClass again, supplying PROCESS_BACKGROUND_MODE_END. The same can be done at the thread level via SetThreadPriorityand THREAD_BACKGROUND_MODE_BEGIN/END.

执行此操作的正确方法是使用PROCESS_BACKGROUND_MODE_BEGIN调用SetProcessPriorityClass以启动后台模式。这会导致非常低(后台)I/O 优先级和空闲 CPU 优先级。完成后,再次调用 SetProcessPriorityClass,提供PROCESS_BACKGROUND_MODE_END。同样可以通过SetThreadPriority和 THREAD_BACKGROUND_MODE_BEGIN/END在线程级别完成。

If you want to directly set the I/O priority, independently of the CPU priority, you must use the NT native APIs. I documented it here, but did not include code examples as we all know they get ripped verbatim.

如果要直接设置 I/O 优先级,独立于 CPU 优先级,则必须使用 NT 原生 API。我在这里记录了它,但没有包括代码示例,因为我们都知道它们会被逐字删除。

The API you want is the NT Native API NtSetInformationProcess. Using this API you can change the I/O priority. This API accepts a 'class' variable telling it what type of information about the process you want to change, that class variable must be set to ProcessIoPriority. You can then set the entire process's I/O priority in this manner.

您想要的 API 是 NT Native API NtSetInformationProcess。使用此 API,您可以更改 I/O 优先级。这个 API 接受一个“类”变量,告诉它你想改变什么类型的进程信息,这个类变量必须设置为 ProcessIoPriority。然后您可以通过这种方式设置整个进程的 I/O 优先级。

Similarly, the I/O priority can be retrieved via NtQueryInformationProcess.

类似地,可以通过NtQueryInformationProcess检索 I/O 优先级。

The bad news is that the priority levels are a bit limited. Critical is reserved for system paging operations. That leaves you with Normaland Very Low(Background). Low and High may or may not be implemented in newer editions of Windows. There seems to be partial support, at the very least.

坏消息是优先级有点有限。关键是为系统分页操作保留的。这给你留下了正常非常低(背景)。Low 和 High 可能会或可能不会在较新版本的 Windows 中实现。至少似乎有部分支持。

If you have no experience with the NT Native APIs, the first thing to do is understand them. Once you do, you'll see it is as simple as a single API call.

如果您没有使用 NT Native API 的经验,首先要做的是了解它们。完成后,您会发现它就像单个 API 调用一样简单。

回答by Michel Lemay

Be sure to align FILE_IO_PRIORITY_HINT_INFOstructure properly when calling SetFileInformationByHandle.

FILE_IO_PRIORITY_HINT_INFO调用时一定要正确对齐结构SetFileInformationByHandle

Otherwise, you will get a ERROR_NOACCESS(error 998, 0x000003E6).

否则,您将收到ERROR_NOACCESS(错误 998, 0x000003E6)。

_declspec(align(8)) FILE_IO_PRIORITY_HINT_INFO priorityHint;
priorityHint.PriorityHint = IoPriorityHintLow;

BOOL ret = SetFileInformationByHandle(hFile, FileIoPriorityHintInfo, &priorityHint, sizeof(FILE_IO_PRIORITY_HINT_INFO));
DWORD err = GetLastError();

回答by dodgy_coder

Just an update for this - it can all be done via .NET without resorting to WinAPI ...

只是对此的更新 - 这一切都可以通过 .NET 完成,而无需求助于 WinAPI ...

// Set the current process to run at 'High' Priority
System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess();
process.PriorityClass = System.Diagnostics.ProcessPriorityClass.High;

// Set the current thread to run at 'Highest' Priority
Thread thread = System.Threading.Thread.CurrentThread;
thread.Priority = ThreadPriority.Highest;

I've tried the above setting the process priority in a WPF application and it works fine. Haven't needed to set thread priority.

我已经尝试了上述在 WPF 应用程序中设置进程优先级的方法,它工作正常。不需要设置线程优先级。

EDIT: this above relates to CPU priority of a process, as opposed to I/O priority, however there may be some correlation / connection between a process's CPU priority and its I/O priority.

编辑:以上与进程的 CPU 优先级有关,而不是 I/O 优先级,但是进程的 CPU 优先级与其 I/O 优先级之间可能存在某种关联/联系。

回答by colin lamarre

If you want critical I/O priority on files your app is dealing with, I believe renaming the files to .mp3 will get you that! Windows does this for media files like .mp3, .mp4 etc It can be observed with Process Hacker in the Disk tab, as soon as anything reads mp3's you'll see they are all in critical I/O. I haven't found any documentation about this, there might be a registry setting?

如果您希望应用程序处理的文件具有关键 I/O 优先级,我相信将文件重命名为 .mp3 会让您满意!Windows 对 .mp3、.mp4 等媒体文件执行此操作 可以使用“磁盘”选项卡中的 Process Hacker 进行观察,只要有任何读取 mp3 的内容,您就会看到它们都处于关键 I/O 中。我还没有找到任何关于此的文档,可能有注册表设置?

Edit: This was on Win 7, I just tried on Win 10 and it's not the same, I saw it go to high priority once but usually normal, but never critical. While writing this I tried a Win 7 VM and it didn't do it there either! I don't know why my main Win 7 does it lol wonder if some third party but what? anyone know?

编辑:这是在 Win 7 上,我刚刚在 Win 10 上尝试过,但它不一样,我看到它曾经被设置为高优先级,但通常是正常的,但从不重要。在写这篇文章时,我尝试了一个 Win 7 VM,但它也没有在那里做!我不知道为什么我的主要 Win 7 不知道是否有第三方但是什么?有人知道吗?