ПРІМЕЧАНІЕПроцесс підсистеми Windows названий Csrss.exe тому, що в Windows NT все підсистеми спочатку передбачалося виконувати як потоки всередині єдиного загальносистемного процесу. Коли підсистеми POSIX і OS / 2 були виділені у власні процеси, ім'я файлу процесу підсистеми Windows залишилося колишнім.
Змішувати виклики функцій різних підсистем можна. Іншими словами, додатки POSIX можуть викликати тільки сервіси, що експортуються підсистемою POSIX, а додатки Windows - лише сервіси, що експортуються підсистемою Windows. Як ви ще переконаєтеся, це обмеження послужило однією з причин, по якій вихідна підсистема POSIX, що реалізує вельми обмежений набір функцій (тільки POSIX 1003.1), не стала корисною середовищем для перенесення в неї UNIX-додатків.
Ми вже говорили, що призначені для користувача програми не можуть викликати системні сервіси Windows безпосередньо. Замість цього вони звертаються до DLL підсистем. Ці DLL надають документований інтерфейс між програмами і викликається ними підсистемою. Так, DLL підсистеми Windows (Kernel32.dll, Advapi32.dll, User32.dll і Gdi32.dll) реалізують функції Windows API. DLL підсистеми POSIX (Psxdll.dll) реалізує POSIX API.
Це показує, що Notepad є GUI-програмою, a Cmd - консольної, або програмою текстового режиму. Хоча висновок утиліти Exetype повідомляє про наявність двох різних підсистем для GUI- і консольних програм, насправді існує лише одна підсистема Windows. Крім того, Windows не підтримує процесор Intel 386 (або 486, якщо це має якесь значення) - текст повідомлень, що виводяться програмою Exetype, просто не оновили.
При виклику додатком однієї з функцій DLL підсистеми можливо одне з трьох.
(O) Функція повністю реалізована в призначеному для користувача режимі всередині DLL підсистеми. Інакше кажучи, ніяких повідомлень процесу підсистеми оточення не посилати, і виклику сервісів виконавчої системи Windows не відбувається. Після виконання функції в призначеному для користувача режимі результат повертається викликала її програмі. До таких засобів можуть служити GetCurrentProcess (завжди повертає -1, значення, визначене для посилання на поточний процес у всіх функціях, пов'язаних з процесами) і GetCurrentProcessId (ідентифікатор процесу не змінюється протягом його терміну життя, тому його можна отримати з кеша, що дозволяє уникнути перемикання в режим ядра).
(O) Функція вимагає одного або більше викликів виконавчої системи Windows. Наприклад, Windows-функції ReadFile і WriteFile звертаються до внутрішніх недокументованим сервісів введення-виведення - відповідно до NtReadFile і NtWriteFile.
(O) Функція вимагає виконання будь-яких операцій в процесі підсистеми оточення (такі процеси, що працюють в режимі користувача, відповідають за обслуговування клієнтських додатків, які виконуються під їх контролем). B цьому випадку підсистемі оточення видається клієнт-серверний запит через повідомлення з вимогою виконати будь-яку операцію, і DLL підсистеми, перш ніж повернути управління викликала програмі, чекає відповідного відповіді.
Деякі функції на кшталт CreateProcess і CreateThread можуть вимагати виконання як другого, так і третього пункту.
Хоча структура Windows дозволяє підтримувати кілька незалежних підсистем оточення, з практичної точки зору було б незручно включати до складу кожної підсистеми свій код для обробки вікон і відображення введення-виведення. Це призвело б до дублювання системних функцій і в кінцевому рахунку негативно відбилося б на обсязі та продуктивності системи. Оскільки головною підсистемою була Windows, розробники вирішили розмістити ці базові функції саме в ній. Так що інші підсистеми для відображення введення-виведення викликають відповідні сервіси Windows. (До речі, подивившись на тип підсистеми в заголовках їх файлів, ви переконаєтеся, що фактично вони є виконуваними файлами Windows.)
Тепер ближче познайомимося з кожної підсистемою оточення.
підсистема Windows
Так що ж залишається в тій частині процесу підсистеми Windows, яка працює в режимі користувача? Оскільки консольні програми не перемальовували вікна, всі операції по відображенні і оновленню консольних і текстових вікон проводяться саме цією частиною Windows. Побачити її діяльність нескладно: просто відкрийте вікно командного рядка і перетягніть поверх нього інше вікно. Ви побачите, що процес підсистеми Windows починає витрачати процесорний час, перемальовуючи консольне вікно. Крім підтримки консольних вікон, тільки невелика частина Windows-функцій посилає повідомлення процесу підсистеми Windows. K них відносяться функції, що відповідають за створення і завершення процесів і потоків, призначення букв мережевих дисків, створення тимчасових файлів. Як правило, Windows-додаток нечасто перемикає (якщо взагалі перемикає) контекст в процес підсистеми Windows.
He чи постраждала стабільність Windows від перекладу USER і GDI в режим ядра?
Деякі цікавляться, чи не вплине на стабільність системи переклад такої значної частини коду в режим ядра. Ho ризик зниження стабільності системи мінімальний. Справа в тому, що до Windows NT 4 (так само як і в даний час) помилка на зразок порушення доступу (access violation) в процесі підсистеми Windows призначеного для користувача режиму (Csrss.exe) приводила до краху системи, тому що процес підсистеми Windows був і залишається життєво важливим для функціонування всієї системи. Оскільки структури даних, що визначають вікна на екрані, містяться саме в цьому процесі, його загибель призводить до знищення призначеного для користувача інтерфейсу. Однак навіть при функціонуванні Windows в якості сервера без інтерактивних процесів система не могла б працювати без Csrss, оскільки серверні процеси іноді використовують віконні повідомлення для контролю внутрішнього стану додатків. Так що в Windows помилки на кшталт порушення доступу в тому ж коді, тільки виконується в режимі ядра, просто швидше призводять до краху - виключення в режимі ядра вимагають припинення роботи системи.
Правда, теоретично з'являється інша небезпека. Оскільки цей код виконується в режимі ядра, помилка (наприклад, застосування невірного покажчика) може пошкодити захищені структури даних режиму ядра. До Windows NT 4 це могло привести до порушення доступу, так як запис в сторінки режиму ядра з призначеного для користувача режиму не дозволяється. Ho результатом став би крах системи. Тепер же при виконанні коду в режимі ядра запис на будь-яку сторінку пам'яті по невірному вказівником не обов'язково викличе негайний крах системи. Ho, якщо при цьому будуть пошкоджені якісь структури даних, крах швидше за все відбудеться. Проте виникає ризик, що через такого покажчика буде пошкоджена не структура даних, а буфер пам'яті, і це призведе до повернення користувальницької програмі або записи на диск невірних даних.
Існує ще один негативний наслідок перекладу графічних драйверів в режим ядра. Раніше деякі частини графічного драйвера виконувалися в Csrss, а решта частини - в режимі ядра. Тепер весь драйвер працює тільки в режимі ядра. Так як не всі драйвери підтримуваних Windows графічних пристроїв розробляються Microsoft, вона тісно співпрацює з виробниками обладнання, щоб гарантувати розробку ними надійних і ефективних драйверів. Все що поставляються з системою драйвери тестуються так само ретельно, як і інші компоненти виконавчої системи.
Нарешті, важливо розуміти, що така схема (при якій підсистема підтримки вікон і графіки виконується в режимі ядра) не є принципово ризикованою. Ідентичний підхід використовується для багатьох інших драйверів пристроїв (наприклад, мережевих карт і жорстких дисків). Всі ці драйвери, що виконуються в режимі ядра, ніколи не знижували надійності Windows NT
Деякі поширюють вигадки щодо зниження ефективності витісняє багатозадачності Windows через переведення диспетчера вікон і GDI в режим ядра. Теорія, яка стоїть за цією точкою зору, - збільшується час, що витрачається на додаткову обробку Windows в режимі ядра. Ця думка з'явилася в результаті помилкового розуміння архітектури Windows. Дійсно, у багатьох інших операційних системах, формально підтримують багатозадачність, планувальник ніколи не витісняє потоки, що виконуються в режимі ядра, або витісняє, але лише в окремих ситуаціях. Однак в Windows будь-які потоки, що виконуються в режимі ядра, плануються і витісняються так само, як і потоки користувальницького режиму, - код виконавчої системи повністю реентерабелен. Крім багатьох інших міркувань, це просто необхідно для досягнення високого рівня масштабованості системи на обладнанні з підтримкою SMR.
Інший напрямок спекуляцій стосувалося зниження масштабованості SMP в результаті вже описаних змін. Теоретичні обгрунтування були такими: раніше у взаємодії між додатком і диспетчером вікон або GDI брали участь два потоку-, один - в додатку і один - в Csrss.exe. Тому в SMP-системах, де ці потоки можуть виконуватися паралельно, пропускна здатність зростає. Це свідчить про нерозуміння технологій, які застосовувались до Windows NT 4. B більшості випадків клієнтські програми викликають процес підсистеми Windows синхронно, т. Е. Клієнтський потік повністю блокується в очікуванні обробки виклику серверним потоком і поновлюється тільки після цього. Так що ніякої паралелізм в SMP-системах недосяжний. Це явище легко спостерігати в SMP-системах на прикладі додатків, які працювали з графікою. При цьому виявиться, що в двухпроцессорной системі кожен процесор завантажений на 50%; також легко помітити єдиний потік Csrss, відокремлений від потоку додатки. Дійсно, оскільки два потоки тісно взаємодіють і знаходяться в подібному стані, для підтримки синхронізації процесорам доводиться постійно скидати кеш. Саме з цієї причини однопоточні графічні додатки в SMP-системах під управлінням Windows NT 3.51 зазвичай виконуються повільніше, ніж в однопроцесорних системах.
B результаті змін, внесених в Windows NT 4, вдалося підвищити пропускну здатність SMP-систем для додатків, що інтенсивно використовують диспетчер вікон і GDI, - особливо коли в додатку працює більше одного потоку. При наявності двох потоків додатки на двухпроцессорной машині під управлінням Windows NT 3.51 за процесорний час конкурують в цілому чотири потоки (два - в додатку і два - в Csrss). Хоча в кожен момент до виконання готові, як правило, лише два потоки, їх неузгодженість веде до втрати локальності посилань і синхронізації кеша. Це відбувається швидше за все через перемикання потоків додатки з одного процесора на інший. B Windows NT 4 кожен з двох потоків додатки по суті має власний процесор, а механізм автоматичної прив'язки потоків в Windows намагається постійно виконувати даний потік на одному і тому ж процесорі, максимально збільшуючи локальність посилань і зводячи до мінімуму потребу в синхронізації кеш-пам'яті індивідуальних процесорів .
B закінчення відзначимо, що підвищення продуктивності в результаті перекладу диспетчера вікон і GDI з призначеного для користувача режиму в режим ядра досягнуто без скільки-небудь значимого зниження стабільності і надійності системи - навіть в разі кількох сеансів, створених в конфігурації з підтримкою Terminal Services.
підсистема POSIX
Підсистема OS / 2
Як буде детально показано в главі 6, потоки є елементами виконуваної програми і, як такі, підлягають плануванню (підключення до процесора за певною схемою). B OS / 2 всього 64 рівня пріоритетів (від 0 до 63), а в Windows - 32 (від 0 до 31). Незважаючи на це, 64 рівня пріоритетів OS / 2 проектуються на динамічні пріоритети Windows з 1-го по 15-й. Потоки OS / 2, що виконуються в Windows, ніколи не отримують пріоритети реального часу (16-31).