Здравствуйте.
В Университете задали лабораторную работу, в процессе выполнения которой необходимо создать, как можно больше потоков с помощью функции CreateThread.
(Отлично осознаю, что задача абсолютно искусственна и при реальной необходимости лучше воспользоваться Threadpool, либо IO)
Первое ограничение на количество потоков накладывает отношение размера адресного пространства всего потока к размеру стека процесса. Размер стека, создаваемого потока, задается
отсюда:
To change the initially committed stack space, use the dwStackSize parameter of the CreateThread, CreateRemoteThread, or CreateFiber function. This value is rounded up to the nearest page.
Перелопатил множество статей о других ограничениях, лучшей из которых могу назвать следующую:
"Преодолевая границы Windows: процессы и потоки". Она является переводом статьи Марка Руссиновича.
Но к необходимости много искать в интернете меня привел следующий код:
...
for (int i = 0; i < MAX; i++){
handles[i] = CreateThread(NULL, 1, ThreadProc, NULL, STACK_SIZE_PARAM_IS_A_RESERVATION , NULL);
...
В моем представлении, которое опирается на документацию, в данном случае стек потока должен быть равен 64 КБ (размеру страницы в целевой системе — Windows 7 SP1). На деле же, согласно
vmmap получается следующая картина:
Утилита, которая используется в статье Марка: testlimit с ключами -t -n(задает минимальный размер стека). Так же выделяет блоки стека по 1024 Кб, вместо 64 Кб.
В операционных системах Windows 2003 Server и Windows XP код, приведенный выше, создает потоки с размером стека равным 64 Кб. Для запуска в системы устанавливался пакет VS 2010 C++ Redist.
После тестирования в других ОС мне в голову пришла крамольная мысль об ошибке внутри самой Windows 7, потому что после ряда тестов, удалось выявить следующую закономерность:
Код:
handles[i] = CreateThread(NULL, 4096, ThreadProc, NULL, STACK_SIZE_PARAM_IS_A_RESERVATION , NULL);
Создает поток с размером стека в 1 Мб (значение по умолчанию).
Код:
handles[i] = CreateThread(NULL, 4097, ThreadProc, NULL, STACK_SIZE_PARAM_IS_A_RESERVATION , NULL);
Создает поток с размером стека в 64 Кб (ближайшая страница).
Дальнейшие опыты показали, что при значения dwStackSize 0 — применяется значение по умолчанию, от 1 до 4096 значение по умолчанию, от 4097 до 65536 — 64 Кб, при 65537 — 128 Кб. Что наталкивает на мысль об ошибке округления внутри функции, находящейся в ядре ОС, и отвечающей за создание потоков.
Резюмирую список вопросов:
1. Действительно ли при 0 < dwStackSize <= 64 Кб должно резервироваться 64 Кб?
2. Пакеты для Microsoft Visual C++ X Redistributable Package являются ли прослойкой между приложением и вызовом системных функций, либо же функции WinAPI, к примеру, CreateThread вызываются напрямую?
3. Если же имеет место ошибка в функции WinAPI, куда можно писать баг репорт?
Спасибо, за внимание. Мой первый пост на rsdn, выслушаю любую критику по оформлению.
Здравствуйте, found, Вы писали:
F>1. Действительно ли при 0 < dwStackSize <= 64 Кб должно резервироваться 64 Кб?
Согласно документации должен резервироваться объём, кратный размеру system allocation granularity.
У меня на W2008R2 x64 GetSystemInfo возвращает dwAllocationGranularity == 65536 байт, что совпадает с написанным в MSDN.
F>2. Пакеты для Microsoft Visual C++ X Redistributable Package являются ли прослойкой между приложением и вызовом системных функций, либо же функции WinAPI, к примеру, CreateThread вызываются напрямую?
Напрямую.
F>3. Если же имеет место ошибка в функции WinAPI, куда можно писать баг репорт?
Я бы для начала попробовал бы сделать наглядные примеры и попытался бы написать на форум к Руссиновичу.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Резервирование размера не кратного allocation granularity — бессмысленно. Ибо все равно эффективно отожрет те же n*64к памяти.
Мафиозная диктатура это нестабильность. Если не мафиозная диктатура, то Конституция и демократия.