2009-12-04 1 views
1

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

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

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() изменяется, но общее использование памяти приложения (от пса/верхнего выхода/ртара) не изменилось:

OLD: 10485760 , NEW: 65536 - MIN: 16384

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

Мои вопросы:

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

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

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

+0

Глупый вопрос, но после того, как вы изменили размер стека с помощью 'pthread_attr_setstacksize()', используете ли вы 'attr', когда вы действительно создаете поток? Можем ли мы увидеть, как вы называете 'pthread_create()'? –

+0

Конечно, я обновил свой пост. –

ответ

2

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

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

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

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

+0

Это именно то, что он делает, проверить линию 2 своего источника! – Puppe

+0

Да, Puppe, это именно то, что я делаю. Это не так, как я ожидал, даже с приемлемым размером стека. Что касается Q3, я уверен, что есть сторонние библиотеки, вокруг которых можно отключить стеки даже для процессов. Таким образом, должен быть способ моделирования стека в куче. –

+0

@eyazici - Хорошо, ну, указатель стека - это регистр CPU, и вы можете установить его на все, что хотите, включая что-то, что вы получили от malloc() или mmap(). Но из вашего вопроса я понятия не имел, что вы спрашивали - и, даже если вы его достали из другого места, это все еще стек, он все равно будет потреблять память и т. Д. – asveikau

1

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

+0

Это 32-разрядная версия CentOS 5.3, ядро ​​2.6.18 –

 Смежные вопросы

  • Нет связанных вопросов^_^