Предотвратить минимизацию рабочего набора памяти в консольном приложении? - PullRequest
6 голосов
/ 22 января 2010

Я хочу предотвратить минимизацию рабочего набора памяти в консольном приложении. В приложении для Windows я могу сделать переопределением сообщений SC_MINIMIZE . Но как я могу перехватить SC_MINIMIZE в консольном приложении? Или я могу предотвратить минимизацию рабочего набора памяти другими способами?

Я использую Visual Studio 2005 C ++. У кого-то есть проблемы, и решение не радует. :( http://www.eggheadcafe.com/software/aspnet/30953826/working-set-and-console-a.aspx

Спасибо, заранее.

Ответы [ 6 ]

6 голосов
/ 30 января 2010

Обрезка рабочего набора может быть предотвращена только путем блокировки страниц в памяти, либо путем явной блокировки их с помощью VirtualLock , либо путем сопоставления памяти с AWE . Но обе операции чрезвычайно привилегированы и требуют, чтобы приложение запускалось под учетной записью, которой предоставлена ​​«Блокировка страниц в памяти». привилегии, см. Как: включить опцию блокировки страниц в памяти . По умолчанию никто, кроме администраторов, не имеет этой привилегии.

Технически, это ответ, который вы ищете (пропуская «второстепенные» детали того, как определить регионы для блокировки). Но ваш вопрос указывает на то, что вы находитесь на неверном пути.

Обрезка рабочего набора - это то, что происходит часто и не имеет серьезных побочных эффектов. Скорее всего, вы путаете усечение с разбиением на страницы памяти, но они представляют собой отдельные этапы времени жизни страницы памяти. Обрезка происходит, когда ОС удаляет отображение страницы из процесса и помещает страницу в список ожидания. Это очень быстрая и простая операция: страница добавляется в список ожидания, и pte помечается соответствующим образом. Операции ввода-вывода не выполняются, физический объем оперативной памяти не изменяется. Когда и если процесс снова обращается к обрезанной странице, возникает мягкая ошибка . Промах TLB вызовет переход в землю ядра, ядро ​​найдет страницу в списке ожидания и перераспределит ее процессу. Быстро, быстро, легко, опять же, никаких операций ввода-вывода не происходит, а также содержимое оперативной памяти не изменяется Таким образом, процесс, у которого обрезан весь рабочий набор, довольно быстро восстановит весь активный набор (микросекунды), если будет продолжать ссылаться на страницы.

Только когда ОС требуется новые страницы для своего бесплатного списка, она просматривает резервный список, берет самую старую страницу и фактически заменяет ее на диск. В этой ситуации действительно происходит ввод-вывод, а содержимое ОЗУ обнуляется. Когда процесс снова обращается к странице, возникает жесткий сбой . Мисс TLB разбудит ядро, проверит список pte, и теперь произойдет «реальная» ошибка страницы: выделяется новая свободная страница, содержимое читается с диска, а затем страница выделяется процессу и выполнение возобновляется с места пропуска TLB.

Как вы можете видеть, существует огромная разница между обрезкой рабочего набора и подкачкой памяти. Если ваше консольное приложение обрезано, не переживайте. Вы нанесете неисчислимый больший ущерб здоровью системы, блокируя страницы в памяти. И, между прочим, вы также делаете подобный плохой пользовательский опыт, отказываясь минимизировать, когда вас об этом просят, просто потому, что вы неправильно понимаете жизненный цикл страницы.

Это правда, что существуют процессы, которые имеют законное требование поддерживать рабочий режим как можно более горячим. Все эти процессы всегда реализуются как сервисы. Службы получают выгоду от более мягкой политики обрезки от ОС, и эта политика фактически настраивается.

Если вы действительно обеспокоены системной памятью и хотите помочь ОС, вам следует зарегистрироваться для уведомлений о памяти, используя CreateMemoryResourceNotification и реагировать на нехватку памяти, освобождая свои кэш-памяти, и увеличивать ваш кеш возвращается, когда вы получаете уведомление о доступности свободной памяти.

3 голосов
/ 26 января 2010

SetProcessWorkingSetSize(Ex) или используйте VirtualLock в диапазоне, который вы хотите сохранить в физической памяти.

И то, и другое отрицательно повлияет на производительность системы под нагрузкой, но я подозреваю, что вам сейчас все равно.

2 голосов
/ 22 января 2010

Поскольку в консольных приложениях по умолчанию не работает цикл сообщений, следовательно, вы не сможете получить доступ к стандартным сообщениям Windows в своем консольном приложении.

1 голос
/ 22 января 2010

Консольные приложения не получают оконных сообщений, поэтому нет способа определить, находится ли приложение перед пользователем или нет. Вам придется разработать другие стратегии (возможно, таймер активности пользователя), чтобы освободить память, когда приложение не используется.

Вы также можете реализовать свою собственную оболочку, похожую на консоль, но это не простая задача, чтобы получить правильную.

0 голосов
/ 31 января 2010

Как насчет отключения сворачивания в системном меню консоли?

HWND hwnd = GetConsoleWindow(void);
HMENU hmenu = GetSystemMenu(hwnd, FALSE);
EnableMenuItem (hmenu, SC_MINIMIZE, MF_DISABLED | MF_BYCOMMAND);

Вы также можете попробовать отключить кнопку свертывания в окне консоли.

HWND hwnd = GetConsoleWindow(void);
LONG lStyle = GetWindowLong(hwnd, GWL_STYLE);
SetWindowLong(hwnd, GWL_STYLE, lStyle & ~WS_MINIMIZEBOX);
0 голосов
/ 27 января 2010

для этого вы можете использовать очень хитрую / хакерскую работу, которая может быть вашим единственным способом:

SetConsoleTitle("MyConsole"); //at creation
//... 
HWND hWnd = FindWindow(NULL,"MyConsole"); //when it would minimize
ShowWindow(hWnd,SW_MAXIMIZE);

Вы можете даже поиграть с некоторыми свойствами окна, используя HWND

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...