Загрузка процессора

Тема в разделе "WASM.WIN32", создана пользователем Tropez, 26 ноя 2008.

  1. Tropez

    Tropez New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2008
    Сообщения:
    8
    Нижеприведённый код ожидает готовность жёсткого диска выполнять команды.
    Проблема в том, что этот участок кода вызывает 100% загрузку процессора.
    Вызов функции Sleep в фазе ожидания, проблему загрузки CPU решает, но появляется другая - замедление работы программы из-за
    того, что эта функция даёт задержку не менее 10 мс, что в данном случае критично , т.к. жёсткий диск отрабатыват команды менее чем а 5 мс.

    Требуется HELP!
     
  2. Partner

    Partner Павел

    Публикаций:
    0
    Регистрация:
    28 фев 2008
    Сообщения:
    917
    Адрес:
    Los Angeles
    Попробуй Sleep(0)
     
  3. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    Tropez
    ничего себе :) это ты открыл доступ к портам и из юзермода управляешь диском? - так делать полюбому нельзы, особенно в сочетании с командой sleep, которая принудительно передаёт управление другим потокам/процессам и они рано или поздно законфликтят твою команду в порту и твоя прога натворит дел на диске ;)
     
  4. Tropez

    Tropez New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2008
    Сообщения:
    8
    Так я пробовал.
    В таком виде, загрузка проца врё равно 100%, с той разницей, что 50% занимает время ядра операционки (судя по диспетчеру задач)
     
  5. Tropez

    Tropez New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2008
    Сообщения:
    8
    С этого места подробнее.
    Не совсем понимаю, что подразумевается под "законфликтят" и как моя прога начнёт делать не то, что я в неё заложил.
     
  6. Rodin

    Rodin New Member

    Публикаций:
    0
    Регистрация:
    30 апр 2007
    Сообщения:
    125
    Делаю сейчас нечто подобно, только из кернела. Очень много проблем, которые не возникли бы в реальном режиме.
    Самые критичные:
    1) Если читать в PIO то бывает, что отправил команду, ожидаешь данные, а они уже прочитаны виндой... В DMA такого не замечал.
    2) Если чтение работает - посмотри EventLog - увидишь кучу ошибок от atapi.sys/disk.sys, хотя ты свою инфу получаешь. В результате ошибок винда сама переходит из DMA в PIO, хотя в настройках канала стоит "По возможности использовать DMA". Мне не удается вернуть обратно DMA. Из-за этого резко падает производительность - приходится восстанавливаться из образа :dntknw:


    Много чего полезного можно прочитать здесь
    http://www.wasm.ru/forum/viewtopic.php?id=29217
     
  7. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Многозадачные ОС рассчитаны на то, что прикладные программы не будут напрямую общаться с железом, а делать это будет ОС. Ты фактически это нарушаешь, проблем не оберешься. Конфликт твоей программы и драйверов диска обеспечен из-за совместного использования напрямую одного и того же оборудования. Проблемы будут начиная с того, что хард запутается что ему делать - то, что ты говоришь или то, что винда говорит, и заканчивая потерей данных.

    Если очень надо, код стоит выполнять в драйвере режима ядра на IRQL не ниже 2 (Dispatch), исключая переключение потоков (разумеется, винда в это время будет мертво висеть, пока ты не закончишь свои дела) и перехватив обработчик IRQ от контроллера. Да и то я не уверен, что всё учел
     
  8. Rodin

    Rodin New Member

    Публикаций:
    0
    Регистрация:
    30 апр 2007
    Сообщения:
    125
    В данном случае с этим будут определенные проблемы. Если к IDT подключаться через IoConnectInterrupt, то уже подключенный atapi.sys будет перехватывать и обрабатывать твои запросы. Если напрямую патчить IDT, то это подпадает под PatchGuard. Если я все правильно понимаю, то единтвенное решение запретить прерывания от диска на время своей работы.

    Кстати у меня вопрос по многопроцессорности. В каждом процессоре есть своя IDT. Я предполагаю, что для всех процессоров IDT одинакова. Соответственно если приходит IRQ от устройства, то обработчик должен будет вызваться столько раз, сколько процессоров. Где это разруливается - на уровне винды или еще где-то (например на APIC).
     
  9. Tropez

    Tropez New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2008
    Сообщения:
    8
    В моём случае, кофликты с другими драйверами/программами исключены т.к. контроллер через который я общаюсь с диском не зарегистрирован в операционной системе (не стоят никакие драйвера) и диск ни как логический ни как физический в системе естесственно не присутствует.
    Возвращаюсь к вопросу: как передать управление другим потокам/процессам подобно функции Sleep, но на время менее 10 миллисекунд ?
     
  10. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Tropez
    SwitchToThread
     
  11. Tropez

    Tropez New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2008
    Сообщения:
    8
    Не годится.
    Это то же самое, что и Sleep(0).
    Так я пробовал.
    В таком виде, загрузка проца врё равно 100%, с той разницей, что 50% занимает время ядра операционки (судя по диспетчеру задач)
     
  12. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    А другие готовые потоки то есть?
    Если нету тогда загрузка 100% очевидна и вполне нормальна, если больше некому отдавать управление
     
  13. 4VR

    4VR New Member

    Публикаций:
    0
    Регистрация:
    21 ноя 2008
    Сообщения:
    25
    Абсолютное заблуждение. Каждый процессор выполняет свою задачу. У каждого процессора есть своя IDT. Куда придёт прерывание от устройства разрешается путём конфигурирования Apic. Прерывание должен обработать именно тот процессор, на вход которого оно поступило.
     
  14. Tropez

    Tropez New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2008
    Сообщения:
    8
    Я могу ошибаться, но из информации,которую я нашёл в сети, в системах класса NT, есть процесс "Бездействие системы", который выполняет команды HLT, с целью охладить процессор.
    Очень хочется передавать управление ему.
    А вообще мне всё равно, какому процессу я отдам управление.
    Мне важно, чтобы мой процесс, который фактически ничего не выполняет а ждёт событие, не занимал ресурс процессора.
     
  15. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Tropez
    "Передать управление ему" можно либо до возникновения какого-либо события (например, WaitForSingleObject), либо на определённое время (например, Sleep). Т.к. Вы не можете указать ни время, ни хэндл объекта, сигнализацию которого ожидать, (а откуда тогда системе знать, когда выделять Вашему потоку процессорное время?) Вам остаётся только отдавать управление другим ожидающим потокам (SwitchToThread). Т.о. Ваш процесс будет выполнять функцию процесса "Бездействие системы".
     
  16. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Tropez
    Можно сделать задержку (WaitForSingleObject) на ждущем таймере (CreateWaitableTimer+SetWaitableTimer) или мультимедийном (timeSetEvent) предварительно увеличив разрешение timeBeginPeriod(1)
     
  17. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Как уже правильно сказал l_inc - ты не можешь ему отдать управление.

    В статье (которую на днях должен выложить Aquila, надо его пнуть посильнее ;)) описано подробно как потоки получают и теряют управление.
    Действительно есть безымянный процесс, по-разному именуемый в разных менеджерах задач, в виндовом называется System Idle Process (Бездействие системы в русской версии), который содержит по одному потоку на каждый логический процессор в системе. Соответствующий поток получает управление когда нет НИ одного готового к выполнению потока для данного процессора (под готовым имеется в виду Thread->State == Ready).

    Твой же поток всегда будет готовым либо выполняющимся (State == Ready или Running) если у тебя цикл.
    Преждевременно отдать свой квант можно либо функциями ожидания объекта (WaitFor****), либо безусловным ожиданием (Sleep, SleepEx), либо просто завершить квант функцией SwitchToThread (ZwYieldExecution).
    Ожидать объект ты не можешь, поскольку тебе нечего ждать. Ожидать по таймауту можно в принципе, если укажешь разумный таймаут. Соответственно подели время выполнение кода на полное время цикла и узнаешь сколько будет отнимать % кванта процессорного времени твой поток.
    Делать ZwYieldExecution (SwitchToThread) смысла мало - твой поток всегда будет Ready/Running, разница лишь в том, что иногда он будет делиться квантом с другими потоками. Но это и так будет происходить, поскольку Windows по таймеру сама заберет у тебя твой квант, если будешь слишком "жадным".

    Получаем следующее - WaitFor*** ничего не даст, SwitchToThread чтото даст, но почти незаметно. Sleep - даст то, что ты хочешь, если укажешь разумный таймаут, который не нарушит твоего алгоритма
     
  18. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    PS. Поточнее задать время можно прямым вызовом ZwDelayExecution (в сотнях наносекунд) вместо Sleep(Ex), которая является оберткой для нее
     
  19. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    что впрочем отнюдь не гарантирует, что этот уточнённый запрос будет уточнённо исполняться :) ведь timeBeginPeriod на которую опирается Sleep (а значит и её "внутренность" тоже) задаётся в миллисекундах, и те не гарантированы :)
     
  20. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Само собой, я про теоритическое значение. Ну а какая уж точность там получится фиг его знает) не проверял никогда.