Проблема размера стека по умолчанию в NPTL

Я занимаюсь разработкой многопоточного модульного приложения с использованием языка программирования C и NPTL 2.6. Для каждого плагина создается поток POSIX. Проблема в том, что каждый поток имеет свою собственную область стека, так как размер стека по умолчанию зависит от выбора пользователя, в некоторых случаях это может привести к огромному потреблению памяти.

Чтобы предотвратить ненужное использование памяти, я использовал что-то подобное для изменения размера стека перед созданием каждого потока:

pthread_attr_t attr;
pthread_attr_init (&attr);
pthread_attr_getstacksize(&attr, &st1);
if(pthread_attr_setstacksize (&attr, MODULE_THREAD_SIZE) != 0) perror("Stack ERR");
pthread_attr_getstacksize(&attr, &st2); 
printf("OLD:%d, NEW:%d - MIN: %d\n", st1, st2, PTHREAD_STACK_MIN);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
/* "this" is static data structure that stores plugin related data */
pthread_create(&this->runner, &attr, (void *)(void *)this->run, NULL);

РЕДАКТИРОВАТЬ I: добавлен раздел pthread_create().

Это не сработало, как я ожидал, размер стека сообщил pthread_attr_getstacksize() изменено, но общее использование памяти приложением (из вывода ps/top/pmap) не изменилось:

СТАРЫЙ:10485760, НОВЫЙ:65536 - МИНУТА: 16384

Когда я использую ulimit -s MY_STACK_SIZE_LIMIT перед запуском приложения добиваюсь ожидаемого результата.

Мои вопросы:

1-) Есть ли какой-либо переносимый (между вариантами UNIX) способ изменить (по умолчанию) размер стека потока после запуска приложения (конечно, до создания потока)?

2-) Можно ли использовать одну и ту же область стека для каждого потока?

3-) Возможно ли полностью отключить стек для потоков без особой боли?

2 ответа

Ответы для № 2 и № 3 - нет и нет. Каждому потоку нужен стек (куда еще идут ваши локальные переменные и адреса возврата?), И они должны быть уникальными для каждого потока (в противном случае потоки перезаписывают локальные переменные и адреса возврата друг друга, что приводит к краху всех).

Что касается #1... вызов установленного размера стека является как раз ответом на это. Я предлагаю вам определить приемлемый размер для создания ваших тем и установить его.

Что касается того, почему вещи не выглядят правильно для вас в top.... top печально известный лжец об использовании памяти.:-) Неужели вещи не распределяются или не убиваются OOM? Не удалось создать поток? Производительность страдает и страничка на диск увеличивается? Если ответ на эти вопросы - нет, то я не думаю, что есть о чем беспокоиться.

Обновление на основе некоторых комментариев ниже и выше:
Во-первых, 16 КБ все еще достаточно велики для того, что, как вы говорите, не требует много места в стеке. Если вы действительно хотите стать маленьким, я бы хотел сказать 4096 или 8192 для x86 Linux. Во-вторых, да, вы можете установить указатель стека вашего процессора на что-то другое... Но когда вы malloc() или же mmap()Это займет место. Я не знаю, как вы думаете, это поможет установить указатель стека на что-то еще. Тем не менее, если вы действительно чувствуете, что поток, который вызывает main() слишком большой стек (я бы сказал, что это немного сумасшедший) и что pthread_attr_setstacksize() не позволяет вам стать достаточно маленьким (?), тогда, возможно, вы можете посмотреть на непереносимые вещи, такие как создание потоков, вызвав clone() syscall и указание стеков на основе указателя стека основного потока, или буфера из другого места, или чего-то еще. Но вам все еще понадобится стек для каждого потока, и у меня есть чувство top все еще собирается разочаровать вас. Может быть, ваши ожидания немного высоки.

Я тоже видел эту проблему. Непонятно, как учитываются стеки, но "лишнее" пространство засчитывается в общую виртуальную машину, и если вы столкнетесь с границей процесса, у вас возникнут проблемы (даже если вы не используете это пространство). Кажется, это зависит от того, какую версию Linux вы используете (даже в пределах семейства 2.6), и от того, 32-битная или 64-битная версия у вас.

Другие вопросы по тегам