Долаючи кордони windows вивантажуваний і невивантажуваного пули
Цього разу я збираюся розповісти про двох фундаментальних ресурсах ядра, що вивантажується (від англ. Paged) і невивантажуваного (від англ. Nonpaged) пулах, які засновані на перших двох ресурсах і які мають безпосередній вплив на багато інших обмежень системних ресурсів, включаючи максимальне число процесів, об'єктів синхронізації і дескрипторів.
Наприклад, коли програму слід 512-байтний буфер для зберігання даних, диспетчер динамічної пам'яті бере одну з областей, які він може виділити, і зазначає, що перші 512 байт використовуються, повертаючи покажчик на цю ділянку пам'яті і поміщає залишилася пам'ять в список, який він використовує для зберігання інформації про вільні областях динамічної пам'яті.
невивантажуваного пул
Ядро і драйвери пристроїв використовують невивантажуваного пул для зберігання даних, до яких можна звернутися у разі, коли система не може обробити сторінкові помилки. Ядро входить в такий режим у випадках, коли воно виконує процедури обробки переривань (ISR) і відкладені виклики процедур (DPC), які являють собою функції, пов'язані з апаратними перериваннями. Сторінкові помилки також неприпустимі, коли ядро або драйвер пристрою запитують спін-блокування. Вона є єдиним типом блокування, яка може бути використана для ISR і DPC і повинна використовуватися для захисту структур даних, які викликаються з ISR або DPC та інших ISR або DPC, або з коду, що виконується в потоках ядра. Відмова драйвера дотримуватися цих правил закінчується найбільш поширеним кодом помилки: IRQL_NOT_LESS_OR_EQUAL.
Тому невивантажуваного пул завжди знаходиться у фізичній пам'яті і віртуальної пам'яті невивантажуваного пулу призначена фізична пам'ять. Загальні системні структури даних зберігаються в невивантажуваного пулі, включаючи ядро і об'єкти, які представляють процеси і потоки, об'єкти синхронізації, такі як м'ютекси, семафори і події, посилання на файли, які представлені як файлові об'єкти, і пакети запитів вводу / виводу (IRP) , які представлені як операції введення / виводу.
вивантажуваний пул
Вивантажуваний пул, з іншого боку, отримав свою назву тому, що Windows може записати дані, які він зберігає, в файл підкачки, дозволяючи тим самим використовувати фізичну пам'ять, яка при цьому звільняється, в інших цілях. Як і у випадку з віртуальною пам'яттю призначеного для користувача режиму, коли драйвер або система посилається на вивантажуваний пул пам'яті, яких знаходиться в файлі підкачки, і диспетчер пам'яті зчитує дані назад в фізичну пам'ять. Найбільшим споживачем вивантажується пулу, по крайней мере в Windows Vista і більш пізніх ОС, зазвичай є системний реєстр, так як посилання на ключі і інші структури даних реєстру зберігаються в вивантажується пулі. Структури даних, які представлені у вигляді відображаються на пам'ять файлів, які називаються секціями, також зберігаються в вивантажується пулі.
Драйвера пристроїв для виділення вивантажується і невивантажуваного пулу використовують API ExAllocatePoolWithTag. визначаючи тип пулу як один з параметрів. Іншим параметром є 3-байтний тег, який драйвери використовують для унікальної ідентифікації пам'яті, виділеної їм; цей параметр може бути корисним ключем для пошуку драйверів, відсутніх в пулі (про це я розповім нижче).
Є три лічильники, що показують інформацію про використання пулу:
- Пул невивантажуваного байтів;
- Пул вивантажуються байтів (віртуальний розмір вивантажується пулу);
- Пул вивантажуються резидентних байтів.
Однак, не існує будь-яких лічильників продуктивності (performance counters) вказують максимальний розмір цих пулів. Такі дані можна отримати скориставшись командою відладчика ядра! Vm, але, щоб використовувати відладчик ядра в режимі локальної налагодження в Windows Vista і більш пізніх версіях системи, вам необхідно завантажити систему в режимі налагодження, в якому відключено відтворення MPEG2.
Після того, як ви налаштуєте символи, відкрийте діалогове вікно System Information (клікніть на пункті System Information меню View або натисніть Ctrl + I), щоб побачити інформацію про кулю в секції Kernel Memory. Ось як це виглядає в системі Windows XP з 2Гб пам'яті:
32-x бітна Windows XP з 2-ма Гб ОЗУ
64-x бітна Windows XP з 2-ма Гб ОЗУ
32-x бітна Windows XP з 2-ма Гб ОЗУ
І нарешті, ось це обмеження для системи з 64-бітної Windows 7 з 8 Гб пам'яті:
Ось зведена таблиця обмежень на розмір невивантажуваного пулу для різних версій Windows:
32-x бітна Windows XP з 2-ма Гб ОЗУ
64-x бітна Windows 7 з 8-ю Гб ОЗУ
Ось зведена таблиця обмежень на розмір вивантажується пулу для різних операційних систем:
Тестування обмежень на розмір пулу
Оскільки пули ядра використовуються практично кожною операцією ядра, повне їх виснаження може призвести до непередбачуваних результатом. Якщо ви хочете на своєму досвіді подивитися, як поводиться система в разі інтенсивного використання пулу використовуйте утиліту Notmyfault. У неї є функції, які дозволяють здійснити витік деякого зазначеного користувачем обсягу вивантажується або невивантажуваного пулів. Ви можете змінювати цей розмір за своїм бажанням, а після закриття Notmyfault вся зайнята цією програмою пам'ять звільняється:
Не варто запускати цю програму в своїй системі, якщо ви не готові до можливої втрати даних, так як після того, як вільне місце пулу закінчиться, додатки та операції введення / виводу почнуть завершуватися з помилкою. Ви навіть можете отримати синій екран смерті (BSOD), якщо якийсь драйвер не зможе коректно обробити умова вивантаження з пам'яті (що вважається помилкою драйвера). Windows Hardware Quality Laboratory (WHQL) тестує драйвери, використовуючи Driver Verifier - утиліту, вбудовану в Windows - щоб переконатися в тому, що вони можуть обробляти вивантаження з пулу без помилок, однак у вас можуть бути встановлені драйвери сторонніх виробників, які або не пройшли таке тестування, або мають помилки, які не були виявлені під час тестів WHQL.
Я запускав Notmyfault на безлічі тестових систем на віртуальних машинах, щоб побачити, як вони поведуть себе і не зустрінуться з якимись системними помилками. Після того, як невивантажуваного пул на системі з 64-бітної Windows XP б вичерпано, спроба запуску командного рядка завершилася наступним діалоговим вікном:
На одній з тестових систем я побачив повідомлення про помилку, в якому була зазначено, що, можливо, дані були втрачені. Сподіваюся, ви ніколи не побачите подібного діалогового вікна на вашій реальній системі!
Такі ж помилки виникали і в разі вичерпання вивантажується пулу. Ось результати спроби запуску Блокнота з командного рядка на системі з 32-бітної Windows XP, після того як вивантажуваний пул був вичерпаний. Зверніть увагу на те, що Windows не змогла запустити перерисовку заголовка вікна, а також видавала різні помилки при кожній новій спробі запуску програми:
Причина, по якій Windows не зависає після того, як пул був вичерпаний, навіть при тому, що система непрацездатна, полягає в тому, що подібна ситуація може бути тимчасовою, яка виникла внаслідок піку робочого навантаження, після якого пул буде звільнений і система зможе повернутися в нормальний режим роботи. Однак, якщо пул спустошує драйвер (або ядро), причина такого витоку стає важливою. У цьому випадку важливу роль відіграють теги пула, описані на початку цієї статті.
Відстеження витоків пулу
У разі, якщо ви підозрюєте наявність витоку пула і система все ще може запускати додатки, Poolmon - інструмент з набору Windows Driver Kit - покаже вам число виділених областей і кількість незайнятих байтів в цих областях, розділених по типу пулу, а також теги запитів ExAllocatePoolWithTag. Різні комбінації гарячих клавіш дозволяють Poolmon сортувати вміст з різних колонкам; щоб знайти виділені ділянки пам'яті, що являють собою витоку, натисніть клавішу "b" для сортування по байтам, або "d" для сортування по різниці між числом виділених і вільних ділянок пам'яті. Ось знімок, який демонструє роботу Poolmon на системі, де за допомогою Notmyfault був організований витік 14 ділянок пам'яті пулу, кожен приблизно по 100Мб:
Після того, як ви знайшли шуканий тег в лівій колонці (в даному випадку це "Leak"), наступним кроком буде знаходження драйвера, що використовує цей тег. Так як ці теги зберігаються в образі драйвера, ви можете просканувати даний образ на наявність даного тега. Утиліта String від Sysinternals зберігає шукані рядки в зазначеному вами файлі (шукана стрічка за замовчуванням повинна бути не коротше 3-х символів, і, так як більшість образів драйверів знаходяться в директорії% Systemroot% # 92; System32 # 92; Drivers, ви можете відкрити командний рядок, змінити поточну директорію на зазначену і виконати команду "strings * | findstr
Якщо стався збій системи і ви підозрюєте, що це виною цьому виснаження пулу, завантажте дамп-файл цього збою в отладчике Windbg, який включений до складу пакета Debugging Tools for Windows, і переконайтеся в цьому за допомогою команди! Vm. Ось результат запуску цієї команди на системі, в якій Notmyfault вичерпав невивантажуваного пул:
Використовуйте утиліту Strings для пошуку в дампі інформації про драйвер, що використовує тег, певний вами як причина витоку.
На даний момент в цій серії статей я розповів вам про самих фундаментальних обмеженнях Windows, включаючи фізичну пам'ять, віртуальну пам'ять, вивантажуваний і невивантажуваного пули. Наступного разу я розповім про обмеження на кількість процесів і потоків, підтримуваного Windows, які грунтуються на цих основних системних обмеженнях.