Win32 DDK: неправильно ли вызывать API из прерывания драйвера? - PullRequest
1 голос
/ 06 января 2010

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

В бонусной главе Раймонд Чен книга ,

alt text

Раймонд приводит пример ошибки в драйвере звуковой карты:

Исходная функция, вызываемая в время аппаратного прерывания выглядит это в DDK:

void FAR PASCAL midiCallback(NPPORTALLOC pPortAlloc, WORD msg,
                             DWORD dwParam1, DWORD dwParm2) {
   if (pPostAlloc->dwCallback)
      DriverCallBack(pPortalloc->dwCallback, HIWORD(pPortalloc->dwFlags),
                     pPortalloc->hMidi, msg, dwParam1, dwParam2);
}

Их версия функции выглядела как это:

void FAR PASCAL midiCallback(NPPORTALLOC pPortAlloc, WORD msg,
                               DWORD dwParam1, DWORD dwParm2) {
   char szBuf[80];

   if (pPostAlloc->dwCallback) {
      wsprintf(szBuf, " Dc(hMidi=%X,wMsg=%X)", pPortalloc->hMidi, msg);
#ifdef DEBUG
   OutputDebugString(szBuf);
#endif
      DriverCallBack(pPortalloc->dwCallback, HIWORD(pPortalloc->dwFlags),
                     pPortalloc->hMidi, msg, dwParam1, dwParam2);
   }
} 

Мало того, что в розничном коде есть остатки отладочной информации, но это вызов бесперебойно-безопасной функции во время аппаратного прерывания. Если wsprintf функция когда-либо получает Отказаться, система займет сегментный недостаток внутри аппаратное прерывание, которое приводит к довольно быстрая смерть.

Теперь, если бы я посмотрел на этот код, я бы не догадался, что вызов библиотечной функции wsprintf будет проблемой. Что произойдет, если мой код драйвера должен использовать Win32 API?

Что такое ошибка сегмента ? Я понимаю концепцию сбоя страницы : код, который мне нужен, находится на странице, которая была выгружена на жесткий диск, и мне нужно будет вернуться с жесткого диска, прежде чем выполнение кода сможет Продолжить. Что такое ошибка сегмента , когда мы находимся внутри прерывания драйвера устройства?

Является ли ошибка страницы эквивалентом защищенного режима ошибка сегмента ? Как избежать ошибок сегмента? Windows когда-нибудь выменяет код драйвера устройства? Как мне остановить " wsprintf от отбрасывания "? Что может привести к тому, что wsprintf будет "отброшен"? Что такое "выброшенный"? В чем достоинство отбрасывания? Когда это что-то un отбрасывается

Почему вызов API-интерфейса изнутри драйвера плох и как его можно обойти?

1 Ответ

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

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

Windows не может обрабатывать сбои страниц в определенных контекстах, один из которых находится в прерывании. Именно так оно и задумано. Например, представьте, что вы получили ошибку страницы в коде, который считывает данные страниц памяти с диска, как это могло бы справиться с таким случаем? Таким образом, они определяют определенные ограничения на то, какие режимы работы разрешены на странице, а какие нет. Если вы вызываете ошибку страницы в прерывании, ядро ​​принудительно вызывает BSOD.

То, что вы должны делать в контексте прерывания, если вам нужно сделать что-то, что может потребовать подкачки, это поставить в очередь то, что называется отложенным вызовом процедуры ( DPC ) в обработчике прерывания. Затем DPC выполняется на уровне DPC (то, что вы увидите, упомянуто, если вы прочтете некоторые описания функций DDK). Уровень DPC может отображаться на странице, поэтому вы можете использовать любую нужную вам функцию.

Что касается драйвера, вы можете пометить часть своего кода как нестраничную и вы можете выделить non-paged-pool, который является памятью, к которой вы можете обращаться, не вызывая сбоев страниц. wsprintf может быть выгружен, потому что никто не использовал его, и ядро ​​освобождает память.

...