Что именно происходит, когда я создаю новый поток из .NET? - PullRequest
14 голосов
/ 10 июня 2011

Я хочу понять, что именно происходит за кулисами, когда я создаю новый поток в .NET, что-то вроде здесь:

Thread t = new Thread(DoWork); //I am not interested in DoWork per se
t.Start();

1.Какие объекты, связанные с потоками, создаются в ядре CLR и Windows?2. Зачем нужны эти объекты?3. Сколько управляемой / неуправляемой памяти (кучи и стека) выделено в Windows x86, x64?

ОБНОВЛЕНИЕ Я ищу такие объекты, как объект управляемого потока , который, как я предполагаю, t , но, возможно, некоторые другие дополнительные управляемые объекты; объект потока ядра , блок среды пользовательского потока и тому подобное.

Большое спасибо!

Ответы [ 3 ]

9 голосов
/ 11 июня 2011

Win32 и память ядра выделены

Я не совсем уверен, как работает .NET-часть, но если среда выполнения решит создать реальный поток с ОС, она в конечном итоге вызовет Win32 API CreateThread в kernel32.dll, возможно, из mscorlib.ni.dll

По умолчанию новые потоки получают 1 МБ виртуального адреса для стека, который фиксируется по мере необходимости.Это можно контролировать с помощью параметра maxStackSize .Размер стека основного потока определяется параметром в самом исполняемом файле.

В адресном пространстве процесса будет выделен TEB (блок среды потока) ( см. Также ).Кстати, регистр FS на x86 указывает на такие вещи, как локальное хранилище потоков и структурированная обработка исключений (SEH).Вероятно, Win32 выделяет другие вещи, которые не документированы.

При создании потока Win32 происходит обращение к процессу сервера Win32 (csrss.exe).Вы можете видеть, что csrss имеет дескрипторы, открытые для всех процессов Win32 и потоков в Process Explorer для некоторого вида бухгалтерского учета.

DLL-библиотеки, загруженные в процесс, будут уведомлены о новом потоке и могут выделить свою собственную память для отслеживанияthread.

Ядро создаст объект ETHREAD [ layout ] (производный от KTHREAD) из невыгружаемого пула ядра для отслеживания состояния потока.Также будет выделен стек ядра (по умолчанию 12k для x86), который можно выгружать (если поток не находится в состоянии ожидания режима ядра).

Почему так много вещей должны выделять память для потока

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

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

Сколько памяти выделено

Трудно определитьскажем, сколько памяти выделено для потока, так как он распределен по нескольким адресным пространствам и кучам.Она будет варьироваться в зависимости от версии Windows, установленных компонентов и того, что загружено в процесс в настоящее время.

Обычно принято считать, что самая большая стоимость - это 1 МБ адресного пространства, используемого по умолчанию для новых потоков, но даже это ограничение может позволитьмногие сотни будут использоваться в одном процессе без недостатка места.

Если в проекте используется гораздо больше потоков ОС, чем число процессоров в системе, его следует пересмотреть.Рабочие очереди с пулом потоков и легкими потоками с расписанием пользовательского режима с волокнами или реализацией другой библиотеки должны иметь возможность обрабатывать многопоточность, не требуя чрезмерного количества потоков ОС, что делает стоимость памяти потоков неважной.

2 голосов
/ 10 июня 2011

Так что это действительно сложный вопрос, который на самом деле не имеет хорошего ответа на "х".

  1. CLR не требуется для сопоставления одного потока CLR с одним волокном ОС.Так что ... это сложно ответить.Я думаю, что текущая версия .NET (4.0) пытается использовать отношения 1: 1 между потоками CLR и волокнами ОС, когда это возможно, на всех ОС.Предыдущие версии .NET (больше похоже на <= 1.1) Я не уверен, что это имело место на всех ОС.Планировщик обрабатывает большинство этих объектов, и они не будут частью какого-либо графа объектов .NET.Этот планировщик является частью CLR, а не частью объекта <code>Thread.Если вы покопаетесь в IL, вы увидите много внутренних вызовов для фактического выполнения.
  2. Я предполагаю, что вопрос "Зачем нужны эти объекты?"Если это так, то это потому, что хост ОС должен иметь оптоволокно для выполнения кода для этого потока.ThreadPool использование может значительно снизить стоимость их создания каждый раз.
  3. Извините ... зависит.Многое из этого также неуправляемо, что означает, что хост ОС может по-разному обрабатывать это в зависимости от нагрузки и версии системы.

"Логическая абстракция потока управления захвачена экземпляром объекта System.Threading.Thread в библиотеке классов."http://www.ecma -international.org / публикации / файлы / ECMA-ST / Ecma-335.pdf

Таким образом, стандарт EMCA ничего не говорит по данной теме.Но, к счастью, у нас есть ...

"Поскольку объект потока CLR является для каждого волокна, любая свисающая с него информация также является для каждого волокна. Thread.ManagedThreadId возвращает стабильный идентификатор, который обтекает поток CLR. Он не зависит от идентификатора физического потока ОС, что означает, что его использование не подразумевает сродства. Различные волокна, работающие в одном потоке, возвращают разные идентификаторы. "От Джо Даффи http://www.bluebytesoftware.com/blog/2006/11/10/FibersAndTheCLR.aspx

1 голос
/ 10 июня 2011

Смотрите здесь ;существует соответствие между управляемыми (т. е. CLR) примитивами и неуправляемыми (т. е. ядром NT), которые могут ответить на большинство ваших вопросов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...