суббота, 8 мая 2010 г.

Преследуя очередь сообщений...

Это перевод In pursuit of the message queue. Автор: Реймонд Чен.

Каждый поток (или, как его тогда называли, "задача") в 16-ти битной Windows имел очередь сообщений. Конец истории, точка.

При переходе на 32-х разрядную Windows, эту модель поломали, потому что Win32 привнесла такие новые понятия как "рабочие потоки" и "консольные приложения", оба из которых не слишком-то нуждались в этой очереди сообщений. Создание очереди для каждого потока в системе было бы расточительством системных ресурсов (прим.пер.: напомню - типовая машина тех времён имела 4 Мб памяти), поэтому менеджер окон откладывал создание очереди сообщений потока до момента, когда она ему понадобится. Таким образом, потоки, которые не использовали GUI, не должны были платить за то, что они не использовали. Но как только вы отправляли сообщение или проверяли его наличие - и пуф! - у вас волшебным образом появлялась очередь сообщений. С вашей же точки зрения это выглядело так, словно очередь сообщений всегда была тут.

Эта модель создания-по-запросу работала отлично: очереди создавались только когда они были нужны, потоки, которым очередь не была нужна, её не имели, и никого не волновала эта разница. За одним только исключением: PostThreadMessage. Когда я только приступил к написанию этой заметки, я хотел написать, что текущее поведение функции PostThreadMessage является ошибочным. Вместо возврата ошибки, если поток не имеет очереди сообщений, эта функция должна создать иллюзию того, что очередь там была, создавая её по запросу. Но думая об этом в процессе написания заметки, я решил, что текущий дизайн является правильным, хотя он и нарушает принцип "для вас очередь всегда существует".

Функция PostThreadMessage отличается от остальных функций, оперирующих с сообщениями, тем, что она может работать с другим потоком, который не имеет очереди сообщений. Все другие функции, оперирующие с очередью, работают с потоками, которые имеют очередь сообщений. Суммарно вы получаете, что контроль за наличием или отсутствием очереди ложится на сам поток. Если он вызывал функцию работы с очередью - он имеет очередь. Не вызывал - не имеет. Если бы PostThreadMessage создавала бы очередь по запросу, то это позволило бы одному процессу создавать очереди сообщений в другом процессе, причём последний об этом даже не знал бы. После этого исходный процесс мог забить эти только что созданные очереди сообщениями, а жертва бы даже не знала, что у неё есть очередь сообщений, не говоря уже про то, что она битком забита необработанными сообщениями! Ни один поток не смог бы защититься от такого вида атаки.

Делая функцию PostThreadMessage исключением из правила "с вашей точки зрения очередь всегда существует", мы сохраняем контроль за очередью сообщений у самого потока.

1 комментарий:

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.