очередь сообщений потока
От: IWannaTalk  
Дата: 26.06.09 15:49
Оценка:
Привет всем!

Может кто-то знает, как можно получить инфу об очереди сообщений потока?
например, мне нужно получить количество сообщений в очереди на данный момент.
много пишут о недокументированной структуре THREADINFO, но как ее получить нигде не могу найти. или как другим способом получить количество сообщений в очереди?

помогите, плз!
Re: очередь сообщений потока
От: x64 Россия  
Дата: 26.06.09 17:12
Оценка:
Ты уверен, что тебе нужно именно кол-во сообщений? Может быть достаточно будет таких функций как GetQueueStatus() и GetInputState()? Документированного способа нет, поэтому и спрашиваю — нужны ли тебе эти проблемы? Не, мне-то несложно, конечно, написать тебе эти структуры, но сам же потом плеваться будешь с поддержкой всего этого...
Re[2]: очередь сообщений потока
От: IWannaTalk  
Дата: 30.06.09 07:01
Оценка:
Здравствуйте, x64, Вы писали:

x64>Ты уверен, что тебе нужно именно кол-во сообщений? Может быть достаточно будет таких функций как GetQueueStatus() и GetInputState()? Документированного способа нет, поэтому и спрашиваю — нужны ли тебе эти проблемы? Не, мне-то несложно, конечно, написать тебе эти структуры, но сам же потом плеваться будешь с поддержкой всего этого...


да, мне точно надо знать количество сообщений в очереди в любой момент времени
Re[3]: очередь сообщений потока
От: x64 Россия  
Дата: 30.06.09 08:03
Оценка: +1
IWT>да, мне точно надо знать количество сообщений в очереди в любой момент времени

ok, в таком случае пока я роюсь в закромах и ищу то, что тебе нужно, напиши-ка, зачем тебе это вообще понадобилось. Честно говоря, даже интересно просто.
Re[4]: очередь сообщений потока
От: Геннадий Васильев Россия http://www.livejournal.com/users/gesha_x
Дата: 30.06.09 10:02
Оценка: 3 (1)
Здравствуйте, x64, Вы писали:

x64>ok, в таком случае пока я роюсь в закромах и ищу то, что тебе нужно, напиши-ка, зачем тебе это вообще понадобилось. Честно говоря, даже интересно просто.


Не иначе, как для того, чтобы предсказать переполнение.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Re[5]: очередь сообщений потока
От: IWannaTalk  
Дата: 30.06.09 11:07
Оценка: :)
Здравствуйте, Геннадий Васильев, Вы писали:

ГВ>Здравствуйте, x64, Вы писали:


x64>>ok, в таком случае пока я роюсь в закромах и ищу то, что тебе нужно, напиши-ка, зачем тебе это вообще понадобилось. Честно говоря, даже интересно просто.


ГВ>Не иначе, как для того, чтобы предсказать переполнение.


да
Re[6]: очередь сообщений потока
От: Аноним  
Дата: 30.06.09 11:12
Оценка:
x64>>>ok, в таком случае пока я роюсь в закромах и ищу то, что тебе нужно, напиши-ка, зачем тебе это вообще понадобилось. Честно говоря, даже интересно просто.
ГВ>>Не иначе, как для того, чтобы предсказать переполнение.
IWT>да
Переполнение может возникнуть после того как ты получишь количество сообщений в очереди. Так что это не является решением проблемы, лишь уменьая ее вероятность.
Вместо того чтоб гадать на кофейной гуще, сделали бы лучше обработку ошибки от PostThreadMessage.
Re[7]: очередь сообщений потока
От: IWannaTalk  
Дата: 30.06.09 11:16
Оценка:
Здравствуйте, Аноним, Вы писали:

x64>>>>ok, в таком случае пока я роюсь в закромах и ищу то, что тебе нужно, напиши-ка, зачем тебе это вообще понадобилось. Честно говоря, даже интересно просто.

ГВ>>>Не иначе, как для того, чтобы предсказать переполнение.
IWT>>да
А>Переполнение может возникнуть после того как ты получишь количество сообщений в очереди. Так что это не является решением проблемы, лишь уменьая ее вероятность.
А>Вместо того чтоб гадать на кофейной гуще, сделали бы лучше обработку ошибки от PostThreadMessage.

обработка PostThreadMessage есть, мне интересна статистика нагдруженности, которую я хочу писать в лог.
Re[8]: очередь сообщений потока
От: Аноним  
Дата: 30.06.09 11:28
Оценка: 1 (1) +1
x64>>>>>ok, в таком случае пока я роюсь в закромах и ищу то, что тебе нужно, напиши-ка, зачем тебе это вообще понадобилось. Честно говоря, даже интересно просто.
ГВ>>>>Не иначе, как для того, чтобы предсказать переполнение.
IWT>>>да
А>>Переполнение может возникнуть после того как ты получишь количество сообщений в очереди. Так что это не является решением проблемы, лишь уменьая ее вероятность.
А>>Вместо того чтоб гадать на кофейной гуще, сделали бы лучше обработку ошибки от PostThreadMessage.
IWT>обработка PostThreadMessage есть, мне интересна статистика нагдруженности, которую я хочу писать в лог.
InterlockedIncrement(&pending_messages) перед PostThreadMessage и InterlockedDecrement(&pending_messages) после GetMessage — лучшее средство от геморроя.
Re[9]: очередь сообщений потока
От: IWannaTalk  
Дата: 30.06.09 12:02
Оценка:
Здравствуйте, Аноним, Вы писали:

x64>>>>>>ok, в таком случае пока я роюсь в закромах и ищу то, что тебе нужно, напиши-ка, зачем тебе это вообще понадобилось. Честно говоря, даже интересно просто.

ГВ>>>>>Не иначе, как для того, чтобы предсказать переполнение.
IWT>>>>да
А>>>Переполнение может возникнуть после того как ты получишь количество сообщений в очереди. Так что это не является решением проблемы, лишь уменьая ее вероятность.
А>>>Вместо того чтоб гадать на кофейной гуще, сделали бы лучше обработку ошибки от PostThreadMessage.
IWT>>обработка PostThreadMessage есть, мне интересна статистика нагдруженности, которую я хочу писать в лог.
А>InterlockedIncrement(&pending_messages) перед PostThreadMessage и InterlockedDecrement(&pending_messages) после GetMessage — лучшее средство от геморроя.

не так все просто...
Re[10]: очередь сообщений потока
От: Аноним  
Дата: 30.06.09 13:03
Оценка:
x64>>>>>>>ok, в таком случае пока я роюсь в закромах и ищу то, что тебе нужно, напиши-ка, зачем тебе это вообще понадобилось. Честно говоря, даже интересно просто.
ГВ>>>>>>Не иначе, как для того, чтобы предсказать переполнение.
IWT>>>>>да
А>>>>Переполнение может возникнуть после того как ты получишь количество сообщений в очереди. Так что это не является решением проблемы, лишь уменьая ее вероятность.
А>>>>Вместо того чтоб гадать на кофейной гуще, сделали бы лучше обработку ошибки от PostThreadMessage.
IWT>>>обработка PostThreadMessage есть, мне интересна статистика нагдруженности, которую я хочу писать в лог.
А>>InterlockedIncrement(&pending_messages) перед PostThreadMessage и InterlockedDecrement(&pending_messages) после GetMessage — лучшее средство от геморроя.
IWT>не так все просто...
То есть вы сознательно хотите ходить к проктологу ?
Re[11]: очередь сообщений потока
От: IWannaTalk  
Дата: 30.06.09 13:06
Оценка:
Здравствуйте, Аноним, Вы писали:

x64>>>>>>>>ok, в таком случае пока я роюсь в закромах и ищу то, что тебе нужно, напиши-ка, зачем тебе это вообще понадобилось. Честно говоря, даже интересно просто.

ГВ>>>>>>>Не иначе, как для того, чтобы предсказать переполнение.
IWT>>>>>>да
А>>>>>Переполнение может возникнуть после того как ты получишь количество сообщений в очереди. Так что это не является решением проблемы, лишь уменьая ее вероятность.
А>>>>>Вместо того чтоб гадать на кофейной гуще, сделали бы лучше обработку ошибки от PostThreadMessage.
IWT>>>>обработка PostThreadMessage есть, мне интересна статистика нагдруженности, которую я хочу писать в лог.
А>>>InterlockedIncrement(&pending_messages) перед PostThreadMessage и InterlockedDecrement(&pending_messages) после GetMessage — лучшее средство от геморроя.
IWT>>не так все просто...
А>То есть вы сознательно хотите ходить к проктологу ?

ага
Re: очередь сообщений потока
От: x64 Россия  
Дата: 30.06.09 16:53
Оценка:
Ну что, господа, по просьбе трудящихся-кулхацкеров выкладываю некоторые определения, которые помогут в нахождении ответа на вопрос, а где же спрятано кол-во сообщений в очереди потока?

1. Делаем NtQueryInformationThread() с классом ThreadBasicInformation. На выходе получим следующее:

typedef struct _THREAD_BASIC_INFORMATION
{
  NTSTATUS                ExitStatus;
  PVOID                   TebBaseAddress;
  CLIENT_ID               ClientId;
  KAFFINITY               AffinityMask;
  KPRIORITY               Priority;
  KPRIORITY               BasePriority;
}
THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;


2. TebBaseAddress будет указывать на структуру примерно следующего содержания:

typedef struct _TEB
{
  NT_TIB                  Tib;
  PVOID                   EnvironmentPointer;
  CLIENT_ID               Cid;
  PVOID                   ActiveRpcInfo;
  PVOID                   ThreadLocalStoragePointer;
  PPEB                    Peb;
  ULONG                   LastErrorValue;
  ULONG                   CountOfOwnedCriticalSections;
  PVOID                   CsrClientThread;
  PVOID                   Win32ThreadInfo;
  ULONG                   Win32ClientInfo[0x1F];
  PVOID                   WOW32Reserved;
  ULONG                   CurrentLocale;
  ULONG                   FpSoftwareStatusRegister;
  PVOID                   SystemReserved1[0x36];
  PVOID                   Spare1;
  ULONG                   ExceptionCode;
  ULONG                   SpareBytes1[0x28];
  PVOID                   SystemReserved2[0xA];
  ULONG                   GdiRgn;
  ULONG                   GdiPen;
  ULONG                   GdiBrush;
  CLIENT_ID               RealClientId;
  PVOID                   GdiCachedProcessHandle;
  ULONG                   GdiClientPID;
  ULONG                   GdiClientTID;
  PVOID                   GdiThreadLocaleInfo;
  PVOID                   UserReserved[5];
  PVOID                   GlDispatchTable[0x118];
  ULONG                   GlReserved1[0x1A];
  PVOID                   GlReserved2;
  PVOID                   GlSectionInfo;
  PVOID                   GlSection;
  PVOID                   GlTable;
  PVOID                   GlCurrentRC;
  PVOID                   GlContext;
  NTSTATUS                LastStatusValue;
  UNICODE_STRING          StaticUnicodeString;
  WCHAR                   StaticUnicodeBuffer[0x105];
  PVOID                   DeallocationStack;
  PVOID                   TlsSlots[0x40];
  LIST_ENTRY              TlsLinks;
  PVOID                   Vdm;
  PVOID                   ReservedForNtRpc;
  PVOID                   DbgSsReserved[0x2];
  ULONG                   HardErrorDisabled;
  PVOID                   Instrumentation[0x10];
  PVOID                   WinSockData;
  ULONG                   GdiBatchCount;
  ULONG                   Spare2;
  ULONG                   Spare3;
  ULONG                   Spare4;
  PVOID                   ReservedForOle;
  ULONG                   WaitingOnLoaderLock;
  PVOID                   StackCommit;
  PVOID                   StackCommitMax;
  PVOID                   StackReserved;
}
TEB, *PTEB;


3. Поле Win32ThreadInfo здесь будет указывать аккурат на это:

typedef struct tagTHREADINFO
{
    W32THREAD;

//***************************************** begin: USER specific fields

    PTL             ptl;                // Listhead for thread lock list

    PPROCESSINFO    ppi;                // process info struct for this thread

    PQ              pq;                 // keyboard and mouse input queue

    PKL             spklActive;         // active keyboard layout for this thread

    PCLIENTTHREADINFO pcti;             // Info that must be visible from client

    PDESKTOP        rpdesk;
    PDESKTOPINFO    pDeskInfo;          // Desktop info visible to client
    PCLIENTINFO     pClientInfo;        // Client info stored in TEB

    DWORD           TIF_flags;          // TIF_ flags go here.

    PUNICODE_STRING pstrAppName;        // Application module name.

    PSMS            psmsSent;           // Most recent SMS this thread has sent
    PSMS            psmsCurrent;        // Received SMS this thread is currently processing
    PSMS            psmsReceiveList;    // SMSs to be processed

    LONG            timeLast;           // Time, position, and ID of last message
    ULONG_PTR        idLast;

    int             cQuit;
    int             exitCode;

    HDESK           hdesk;              // Desktop handle
    int             cPaintsReady;
    UINT            cTimersReady;

    PMENUSTATE      pMenuState;

    union {
        PTDB            ptdb;           // Win16Task Schedule data for WOW thread
        PWINDOWSTATION  pwinsta;        // Window station for SYSTEM thread
    };

    PSVR_INSTANCE_INFO psiiList;        // thread DDEML instance list
    DWORD           dwExpWinVer;
    DWORD           dwCompatFlags;      // The Win 3.1 Compat flags
    DWORD           dwCompatFlags2;     // new DWORD to extend compat flags for NT5+ features

    PQ              pqAttach;           // calculation variabled used in
                                        // zzzAttachThreadInput()

    PTHREADINFO     ptiSibling;         // pointer to sibling thread info

    PMOVESIZEDATA   pmsd;

    DWORD           fsHooks;                // WHF_ Flags for which hooks are installed
    PHOOK           sphkCurrent;            // Hook this thread is currently processing

    PSBTRACK        pSBTrack;

    HANDLE          hEventQueueClient;
    PKEVENT         pEventQueueServer;
    LIST_ENTRY      PtiLink;            // Link to other threads on desktop
    int             iCursorLevel;       // keep track of each thread's level
    POINT           ptLast;

    PWND            spwndDefaultIme;    // Default IME Window for this thread
    PIMC            spDefaultImc;       // Default input context for this thread
    HKL             hklPrev;            // Previous active keyboard layout
    int             cEnterCount;
    MLIST           mlPost;             // posted message list.
    USHORT          fsChangeBitsRemoved;// Bits removed during PeekMessage
    WCHAR           wchInjected;        // character from last VK_PACKET
    DWORD           fsReserveKeys;      // Keys that must be sent to the active
                                        // active console window.
    PKEVENT        *apEvent;            // Wait array for xxxPollAndWaitForSingleObject
    ACCESS_MASK     amdesk;             // Granted desktop access
    UINT            cWindows;           // Number of windows owned by this thread
    UINT            cVisWindows;        // Number of visible windows on this thread

    PHOOK           aphkStart[CWINHOOKS];   // Hooks registered for this thread
    CLIENTTHREADINFO  cti;              // Use this when no desktop is available
}
THREADINFO;


4. Здесь обратим внимание на поле mlPost:

typedef struct tagMLIST
{
    PQMSG pqmsgRead;
    PQMSG pqmsgWriteLast;
    DWORD cMsgs;
}
MLIST, *PMLIST;


5. Значение cMsgs это и есть кол-во сообщений в очереди, остальные поля выглядят так:

/*
 * Structure definition for messages as they exist on a Q.  Same as MSG
 * structure except for the link-pointer and flags at the end.
 */
typedef struct tagQMSG
{
    PQMSG           pqmsgNext;
    PQMSG           pqmsgPrev;
    MSG             msg;
    LONG_PTR        ExtraInfo;
    DWORD           dwQEvent;
    PTHREADINFO     pti;
}
QMSG;


Ну а дальше, думаю, всё понятно. Два момента, которые хотелось бы упомянуть:

  • Лично не проверял сие, за что купил, за то и продал, но судя по коду Win32k, скорее всего, всё так и есть.
  • Это структуры из Windows 2000, в XP и тем более в Vista скорее всего, что-то поменяли, особенно что касается Win32k.sys.

    Ну я бы не рекомендовал вообще лазить в этот ужас, но если очень хочется — почему нет? В конце концов, чем больше таких вот кривых поделий будет, тем выше моя ценность как разработчика на рынке труда. Удачи!
  • Re[10]: очередь сообщений потока
    От: Геннадий Васильев Россия http://www.livejournal.com/users/gesha_x
    Дата: 30.06.09 17:06
    Оценка:
    Здравствуйте, IWannaTalk, Вы писали:

    А>>>>Вместо того чтоб гадать на кофейной гуще, сделали бы лучше обработку ошибки от PostThreadMessage.

    IWT>>>обработка PostThreadMessage есть, мне интересна статистика нагдруженности, которую я хочу писать в лог.
    А>>InterlockedIncrement(&pending_messages) перед PostThreadMessage и InterlockedDecrement(&pending_messages) после GetMessage — лучшее средство от геморроя.

    IWT>не так все просто...


    А точнее?

    Отслеживать загрузку по длине очереди, ИМХО, не самая хорошая затея. Она либо стремится уйти в нуль даже после всплесков нагрузки, тогда, по крайней мере, в этом аспекте проблем нет, либо в каких-то ситуациях начинает неуправляемо расти (скажем, зацикливание) и скорее всего, здесь хватит простой диагностики ошибки PostThreadMessage.

    Сугубо архитектурно вторую проблему можно решить протоколом обмена данными между потоками. Например, если у нас есть два потока A и B, то A шлёт сообщения B, а B шлёт в сторону A подтверждения их обработки. Пока очередное подтверждение от B не получено, A не отправляет B сообщений. Тихо, мирно, никто никого не перегрузит.
    Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
    P.S.: Винодельческие провинции — это есть рулез!
    Re[11]: очередь сообщений потока
    От: IWannaTalk  
    Дата: 01.07.09 07:16
    Оценка:
    Здравствуйте, Геннадий Васильев, Вы писали:

    ГВ>Здравствуйте, IWannaTalk, Вы писали:


    А>>>>>Вместо того чтоб гадать на кофейной гуще, сделали бы лучше обработку ошибки от PostThreadMessage.

    IWT>>>>обработка PostThreadMessage есть, мне интересна статистика нагдруженности, которую я хочу писать в лог.
    А>>>InterlockedIncrement(&pending_messages) перед PostThreadMessage и InterlockedDecrement(&pending_messages) после GetMessage — лучшее средство от геморроя.

    IWT>>не так все просто...


    ГВ>А точнее?


    ГВ>Отслеживать загрузку по длине очереди, ИМХО, не самая хорошая затея. Она либо стремится уйти в нуль даже после всплесков нагрузки, тогда, по крайней мере, в этом аспекте проблем нет, либо в каких-то ситуациях начинает неуправляемо расти (скажем, зацикливание) и скорее всего, здесь хватит простой диагностики ошибки PostThreadMessage.


    ГВ>Сугубо архитектурно вторую проблему можно решить протоколом обмена данными между потоками. Например, если у нас есть два потока A и B, то A шлёт сообщения B, а B шлёт в сторону A подтверждения их обработки. Пока очередное подтверждение от B не получено, A не отправляет B сообщений. Тихо, мирно, никто никого не перегрузит.


    допустим, 1000 потоков шлют меседжи ОДНОМУ другому. и + некоторые потоки воопще из элиен компонентов. вот в чем сложность! а мне кажеться, что иногда бывает оверфлов очереди, потому что бывает странное поведение приложения. ошибку от PostThreadMessage я могу обработать, но если этот метод вызываеться элиеном?
    если б у меныя был другой способ, я бы не постил ненужный топ.

    ТО: x64
    спс, щас попробую
    Re[12]: очередь сообщений потока
    От: Pavel Dvorkin Россия  
    Дата: 01.07.09 07:48
    Оценка:
    Здравствуйте, IWannaTalk, Вы писали:

    IWT>допустим, 1000 потоков шлют меседжи ОДНОМУ другому.


    Допустить можно в теории что угодно, но если кто-то намерен создать 1000 потоков — мне его жаль.
    With best regards
    Pavel Dvorkin
    Re[12]: очередь сообщений потока
    От: Аноним  
    Дата: 01.07.09 07:54
    Оценка:
    IWT>допустим, 1000 потоков шлют меседжи ОДНОМУ другому. и + некоторые потоки воопще из элиен компонентов. вот в чем сложность!
    Настолько сложно сделать одну функцию и юзать ее вместо PostThreadMessage которая будет считать сообщения, что проще написать драйвер который будет ковыряться в недокументированных структурах? Абсурд
    Re[13]: очередь сообщений потока
    От: Аноним  
    Дата: 01.07.09 08:38
    Оценка: +1
    Здравствуйте, Аноним, Вы писали:

    IWT>>допустим, 1000 потоков шлют меседжи ОДНОМУ другому. и + некоторые потоки воопще из элиен компонентов. вот в чем сложность!


    Внушает Может лучше сразу уволиться, не доводя дело до эксцессов? А то ведь и такое возможно ->

    А>Настолько сложно сделать одну функцию и юзать ее вместо PostThreadMessage которая будет считать сообщения, что проще написать драйвер который будет ковыряться в недокументированных структурах? Абсурд


    Да тут по-моему, достаточно на пальцах подсчитать Вместимость очереди, если мне не изменяет память, 10 000 сообщений. Достаточно каэдому потоку послать их по 10, пока 1001-й поток занят обработкой одного, и вот оно, переполнение. А это вполне вероятно, система только тем и будет заниматься, что потоки переключать, на остальное у неё времени не останется
    Re[13]: очередь сообщений потока
    От: IWannaTalk  
    Дата: 01.07.09 09:28
    Оценка:
    Здравствуйте, Pavel Dvorkin, Вы писали:

    PD>Здравствуйте, IWannaTalk, Вы писали:


    IWT>>допустим, 1000 потоков шлют меседжи ОДНОМУ другому.


    PD>Допустить можно в теории что угодно, но если кто-то намерен создать 1000 потоков — мне его жаль.


    в теории да — на практики до 200 точно доходило....
    Re[13]: очередь сообщений потока
    От: IWannaTalk  
    Дата: 01.07.09 09:30
    Оценка:
    Здравствуйте, Аноним, Вы писали:

    IWT>>допустим, 1000 потоков шлют меседжи ОДНОМУ другому. и + некоторые потоки воопще из элиен компонентов. вот в чем сложность!

    А>Настолько сложно сделать одну функцию и юзать ее вместо PostThreadMessage которая будет считать сообщения, что проще написать драйвер который будет ковыряться в недокументированных структурах? Абсурд

    извините, но вы воопще читаете, что я пишу?
    есть компоненты не нашей команды, которые отправляют этому потоку сообщения. вы предлагаете переписать чужие компоненты тоже иза одной моей прихоти?
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.