реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Завершение потока в pthreads, Не освобождается память
Quasar
сообщение Sep 11 2012, 10:00
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 257
Регистрация: 2-12-06
Из: Default City
Пользователь №: 23 021



Есть приложение, использующее pthread, по ходу выполнения приложения создаются новые потоки, выполнив свою работу они завершаются, делая просто return NULL. Я решил посмотреть, сколько памяти использует мое приложение cat /tmp/PID/status и чего-то не понял:


Код
Name:   app
State:  S (sleeping)
Tgid:   12718
Pid:    12718
PPid:   1
TracerPid:      0
Uid:    0       0       0       0
Gid:    0       0       0       0
FDSize: 32
Groups:
VmPeak:    93568 kB
VmSize:    93568 kB
VmLck:         0 kB
VmHWM:      1184 kB
VmRSS:      1184 kB
VmData:    90304 kB
VmStk:       136 kB
VmExe:       136 kB
VmLib:      2796 kB
VmPTE:        32 kB
VmSwap:        0 kB
Threads:        10



VmData с запуском нового потока только растет, и не уменьшается по его завершению, я так понимаю, что память выделенная под стек не освобождается. Это нормально или я неверно интерпретирую полученные данные?

Плата вот эта.

Код
uname -a
Linux buildroot 2.6.36-rc6 #732 Wed Jun 29 06:03:40 EDT 2011 armv5tejl GNU/Linux



Go to the top of the page
 
+Quote Post
kurtis
сообщение Sep 11 2012, 15:07
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 466
Регистрация: 21-06-05
Пользователь №: 6 205



Если ничего не путаю, то смотреть нужно на RSS, это сколько реально памяти потребляет приложение. И еще использовать команду free, которая выводит обьем свободной памяти.
Go to the top of the page
 
+Quote Post
andron86
сообщение Sep 11 2012, 15:21
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 406
Регистрация: 1-03-06
Пользователь №: 14 821



Цитата(Quasar @ Sep 11 2012, 12:00) *
Есть приложение, использующее pthread, по ходу выполнения приложения создаются новые потоки, выполнив свою работу они завершаются, делая просто return NULL.

А завершаете их правильно?
Go to the top of the page
 
+Quote Post
Quasar
сообщение Sep 11 2012, 16:15
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 257
Регистрация: 2-12-06
Из: Default City
Пользователь №: 23 021



Цитата(andron86 @ Sep 11 2012, 19:21) *
А завершаете их правильно?

Собственно так и завершаю:
Код
static void *rx_thread ( void *ptr ) {
    .
    .
    .
    return NULL;
}


Можно делать pthread_exit(), но я разницы не заметил.
Да, я поглядел /proc/meminfo, свободная память вроде не уменьшается, то есть все таки нормально освобождается все, но мне не ясно, а что же это тогда за виртуальная память и почему она только растет?
Код
cat /proc/meminfo
MemTotal:          60568 kB
MemFree:           40236 kB
Buffers:              16 kB
Cached:             9920 kB
SwapCached:            0 kB
Active:             8132 kB
Inactive:           2952 kB
Active(anon):       1148 kB
Inactive(anon):       12 kB
Active(file):       6984 kB
Inactive(file):     2940 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                 8 kB
Writeback:             0 kB
AnonPages:          1164 kB
Mapped:             1816 kB
Shmem:                12 kB
Slab:               4640 kB
SReclaimable:       2200 kB
SUnreclaim:         2440 kB
KernelStack:         400 kB
PageTables:          280 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:       30284 kB
Committed_AS:     184108 kB
VmallocTotal:     956416 kB
VmallocUsed:      266276 kB
VmallocChunk:     686076 kB
Go to the top of the page
 
+Quote Post
vshemm
сообщение Sep 11 2012, 17:07
Сообщение #5


Частый гость
**

Группа: Участник
Сообщений: 167
Регистрация: 15-08-07
Пользователь №: 29 803



За потребление стека отвечает VmStk, за общее потребление физической памяти (приватный сет) - VmHWM и VmRSS, пик и текущее соответственно. VmData - это количество виртуальной памяти под данные. Растет обычно из-за хипа, его алгоритм так просто витруальную память не возвращает (из-за соображений производительности). По идее, если тест запустить надолго, рост должен остановиться на некотором значении. А для уменьшения VmData придется играть с низкоуровневыми функциями типа brk/sbrk, что является плохой идеей.

Главное, чтобы VmHWM не рос неограниченно.
Go to the top of the page
 
+Quote Post
kiathai
сообщение Oct 19 2012, 09:15
Сообщение #6





Группа: Новичок
Сообщений: 1
Регистрация: 18-05-08
Пользователь №: 37 590



Цитата(andron86 @ Sep 11 2012, 22:21) *
А завершаете их правильно?


При завершении потока, не освобождается память, выделенная под него (стек, описание потока и т.д.).
Чтобы освободить эту память, требуется вызывать pthread_join() из какого-либо другого потока.

Можно создавать потоки, которые будут удаляться автоматически. Для этого надо указывать атрибут PTHREAD_CREATE_DETACHED при создании потока. По умолчанию он не указан.
Go to the top of the page
 
+Quote Post
Andrew2000
сообщение Oct 22 2012, 22:13
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 421
Регистрация: 25-12-04
Пользователь №: 1 675



Цитата(Quasar @ Sep 11 2012, 20:15) *
Можно делать pthread_exit(), но я разницы не заметил.


если в потоке зарегистрировать:

pthread_cleanup_push(thread_exit_func, (void*)&xxxx);
....
pthread_cleanup_pop(1);

функцию для "уборки мусора":

void thread_exit_func (void * arg)
{
xxxx_type *xxxx = (thread_params *)arg;
.....
}

то завершать поток нужно именно по pthread_exit() - это гарантирует вызов "уборщика", а по return оно не вызывается
Go to the top of the page
 
+Quote Post
alx2
сообщение Oct 23 2012, 05:25
Сообщение #8


Местный
***

Группа: Участник
Сообщений: 340
Регистрация: 25-10-05
Из: Пермь, Россия
Пользователь №: 10 091



Цитата(Quasar @ Sep 11 2012, 15:00) *
VmData с запуском нового потока только растет, и не уменьшается по его завершению, я так понимаю, что память выделенная под стек не освобождается. Это нормально или я неверно интерпретирую полученные данные?

Посмотрите вывод команды pmap <PID> - там должно быть хорошо видно, что за блоки памяти выделяются процессом.

Вы создаете detached threads или нет? Если нет, Вы в порождающем потоке выполняете pthread_join()?
Если тоже нет, то ИМХО у Вас будет, как минимум, в памяти оставаться стек каждого отработавшего потока.
Чтобы стек освобождался, Вы должны либо "открепить" созданный поток (выполнить pthread_detach(thr)), либо отслеживать его завершение в родительском потоке и выполнять pthread_join().
Как будет завершаться поток (через вызов pthread_exit() или через return NULL) значения не имеет.


--------------------
Всего наилучшего,
Alex Mogilnikov
Go to the top of the page
 
+Quote Post
Quasar
сообщение Nov 7 2012, 14:29
Сообщение #9


Местный
***

Группа: Свой
Сообщений: 257
Регистрация: 2-12-06
Из: Default City
Пользователь №: 23 021



Цитата(alx2 @ Oct 23 2012, 09:25) *
Посмотрите вывод команды pmap <PID> - там должно быть хорошо видно, что за блоки памяти выделяются процессом.

Вы создаете detached threads или нет? Если нет, Вы в порождающем потоке выполняете pthread_join()?
Если тоже нет, то ИМХО у Вас будет, как минимум, в памяти оставаться стек каждого отработавшего потока.
Чтобы стек освобождался, Вы должны либо "открепить" созданный поток (выполнить pthread_detach(thr)), либо отслеживать его завершение в родительском потоке и выполнять pthread_join().
Как будет завершаться поток (через вызов pthread_exit() или через return NULL) значения не имеет.


Я всегда жду удаления потоков pthread_join'ом. Вывод pmap не понял. В total он пишет, что использовано 270000 KByte, у меня всего 64МБайт, что это за пространство?


Код
pmap 1111 -x
1111: {no such process} /usr/bin/app -c /root/config.ini
Address   Kbytes     PSS   Dirty    Swap  Mode  Mapping
00008000      92      80       0       0  r-xp  /usr/bin/app
00027000       4       4       4       0  rwxp  /usr/bin/app
00028000     132      52      52       0  rwxp  [heap]
4000d000       4       4       4       0  rwxp    [ anon ]
4000e000      28      12       0       0  r-xp  /lib/librt-2.15.so
40015000      28       0       0       0  ---p  /lib/librt-2.15.so
4001c000       4       4       4       0  r-xp  /lib/librt-2.15.so
4001d000       4       4       4       0  rwxp  /lib/librt-2.15.so
40025000      20       4       0       0  r-xp  /usr/lib/libjson.so.0.0.1
4002a000      32       0       0       0  ---p  /usr/lib/libjson.so.0.0.1
40032000       4       4       4       0  rwxp  /usr/lib/libjson.so.0.0.1
40052000       4       4       4       0  rwxp    [ anon ]
40059000       4       4       4       0  rwxp    [ anon ]
40076000     128      17       0       0  r-xp  /lib/libgcc_s.so.1
40096000      28       0       0       0  ---p  /lib/libgcc_s.so.1
4009d000       4       4       4       0  rwxp  /lib/libgcc_s.so.1
400a3000      24      24       0       0  r-xp  /usr/lib/libao.so.4.0.0
400a9000      28       0       0       0  ---p  /usr/lib/libao.so.4.0.0
400b0000       4       4       4       0  rwxp  /usr/lib/libao.so.4.0.0
400b9000       4       4       4       0  rwxp    [ anon ]
400cf000      16       2       0       0  r-xp  /lib/libdl-2.15.so
400d3000      28       0       0       0  ---p  /lib/libdl-2.15.so
400da000       4       4       4       0  r-xp  /lib/libdl-2.15.so
400db000       4       4       4       0  rwxp  /lib/libdl-2.15.so
400dd000       8       8       0       0  r-xp  /usr/lib/ao/plugins-4/libpulse.so
400df000      28       0       0       0  ---p  /usr/lib/ao/plugins-4/libpulse.so
400e6000       4       4       4       0  rwxp  /usr/lib/ao/plugins-4/libpulse.so
400f6000     136      13       0       0  r-xp  /lib/ld-2.15.so
40118000       4       4       4       0  rwxp    [ anon ]
4011f000       4       4       4       0  r-xp  /lib/ld-2.15.so
40120000       4       4       4       0  rwxp  /lib/ld-2.15.so
40121000       8       8       0       0  r-xp  /usr/lib/ao/plugins-4/liboss.so
40123000      32       0       0       0  ---p  /usr/lib/ao/plugins-4/liboss.so
4012b000       4       4       4       0  rwxp  /usr/lib/ao/plugins-4/liboss.so
4012c000      20      16       0       0  r-xp  /usr/lib/ao/plugins-4/libalsa.so
40131000      28       0       0       0  ---p  /usr/lib/ao/plugins-4/libalsa.so
40138000       4       4       4       0  rwxp  /usr/lib/ao/plugins-4/libalsa.so
40146000      12       8       0       0  r-xp  /usr/lib/libpulse-simple.so.0.0.3
40149000      28       0       0       0  ---p  /usr/lib/libpulse-simple.so.0.0.3
40150000       4       4       4       0  rwxp  /usr/lib/libpulse-simple.so.0.0.3
40182000      84      38       0       0  r-xp  /lib/libpthread-2.15.so
40197000      28       0       0       0  ---p  /lib/libpthread-2.15.so
4019e000       4       4       4       0  r-xp  /lib/libpthread-2.15.so
4019f000       4       4       4       0  rwxp  /lib/libpthread-2.15.so
401a0000       8       4       4       0  rwxp    [ anon ]
401a2000     788     372       0       0  r-xp  /usr/lib/libstdc++.so.6.0.16
40267000      28       0       0       0  ---p  /usr/lib/libstdc++.so.6.0.16
4026e000      16      16      16       0  r-xp  /usr/lib/libstdc++.so.6.0.16
40272000       8       8       8       0  rwxp  /usr/lib/libstdc++.so.6.0.16
40274000      24       8       8       0  rwxp    [ anon ]
4027a000     624      26       0       0  r-xp  /lib/libm-2.15.so
40316000      32       0       0       0  ---p  /lib/libm-2.15.so
4031e000       4       4       4       0  r-xp  /lib/libm-2.15.so
4031f000       4       4       4       0  rwxp  /lib/libm-2.15.so
40320000    1296     109       0       0  r-xp  /lib/libc-2.15.so
40464000      28       0       0       0  ---p  /lib/libc-2.15.so
4046b000       8       8       8       0  r-xp  /lib/libc-2.15.so
4046d000       4       4       4       0  rwxp  /lib/libc-2.15.so
4046e000      12      12      12       0  rwxp    [ anon ]
40471000       4       0       0       0  ---p    [ anon ]
40472000    8188       8       8       0  rwxp    [ anon ]
40c71000     264     122       0       0  r-xp  /usr/lib/libpulse.so.0.14.3
40cb3000      28       0       0       0  ---p  /usr/lib/libpulse.so.0.14.3
40cba000       4       4       4       0  rwxp  /usr/lib/libpulse.so.0.14.3
40cbb000     304     124       0       0  r-xp  /usr/lib/pulseaudio/libpulsecommon-2.1.so
40d07000      28       0       0       0  ---p  /usr/lib/pulseaudio/libpulsecommon-2.1.so
40d0e000       4       4       4       0  rwxp  /usr/lib/pulseaudio/libpulsecommon-2.1.so
40d0f000     328      10       0       0  r-xp  /usr/lib/libsndfile.so.1.0.25
40d61000      32       0       0       0  ---p  /usr/lib/libsndfile.so.1.0.25
40d69000       8       8       8       0  rwxp  /usr/lib/libsndfile.so.1.0.25
40d6b000      16       0       0       0  rwxp    [ anon ]
40d6f000     712     136       0       0  r-xp  /usr/lib/libasound.so.2.0.0
40e21000      32       0       0       0  ---p  /usr/lib/libasound.so.2.0.0
40e29000      16      16      16       0  rwxp  /usr/lib/libasound.so.2.0.0
40e2d000       4       0       0       0  ---p    [ anon ]
40e2e000    8188       8       8       0  rwxp    [ anon ]
4164e000       4       0       0       0  ---p    [ anon ]
4164f000    8188       8       8       0  rwxp    [ anon ]
41e4e000       4       0       0       0  ---p    [ anon ]
41e4f000    8188       8       8       0  rwxp    [ anon ]
426d3000       4       0       0       0  ---p    [ anon ]
426d4000    8188       8       8       0  rwxp    [ anon ]
42ed3000       4       0       0       0  ---p    [ anon ]
42ed4000    8188       8       8       0  rwxp    [ anon ]
4376a000       4       0       0       0  ---p    [ anon ]
4376b000    8188       8       8       0  rwxp    [ anon ]
43f6a000       4       0       0       0  ---p    [ anon ]
43f6b000    8188       8       8       0  rwxp    [ anon ]
44812000       4       0       0       0  ---p    [ anon ]
44813000    8188       8       8       0  rwxp    [ anon ]
45012000       4       0       0       0  ---p    [ anon ]
45013000    8188      12      12       0  rwxp    [ anon ]
45902000       4       0       0       0  ---p    [ anon ]
45903000    8188       8       8       0  rwxp    [ anon ]
46200000     132      40      40       0  rwxp    [ anon ]
46221000     892       0       0       0  ---p    [ anon ]
46300000     132      40      40       0  rwxp    [ anon ]
46321000     892       0       0       0  ---p    [ anon ]
46400000       4       0       0       0  ---p    [ anon ]
46401000    8188      20      20       0  rwxp    [ anon ]
46c17000       4       0       0       0  ---p    [ anon ]
46c18000    8188       8       8       0  rwxp    [ anon ]
47417000       4       0       0       0  ---p    [ anon ]
47418000    8188       8       8       0  rwxp    [ anon ]
47c17000       4       0       0       0  ---p    [ anon ]
47c18000    8188      20      20       0  rwxp    [ anon ]
48417000       4       0       0       0  ---p    [ anon ]
48418000    8188       8       8       0  rwxp    [ anon ]
48c17000       4       0       0       0  ---p    [ anon ]
48c18000    8188      20      20       0  rwxp    [ anon ]
49417000       4       0       0       0  ---p    [ anon ]
49418000    8188       8       8       0  rwxp    [ anon ]
49c17000       4       0       0       0  ---p    [ anon ]
49c18000    8188      20      20       0  rwxp    [ anon ]
4a417000       4       0       0       0  ---p    [ anon ]
4a418000    8188       8       8       0  rwxp    [ anon ]
4ac17000       4       0       0       0  ---p    [ anon ]
4ac18000    8188      20      20       0  rwxp    [ anon ]
4b418000       4       0       0       0  ---p    [ anon ]
4b419000    8188      20      20       0  rwxp    [ anon ]
4bc18000       4       0       0       0  ---p    [ anon ]
4bc19000    8188       8       8       0  rwxp    [ anon ]
4c418000       4       0       0       0  ---p    [ anon ]
4c419000    8188       8       8       0  rwxp    [ anon ]
4cc18000       4       0       0       0  ---p    [ anon ]
4cc19000    8188      20      20       0  rwxp    [ anon ]
4d418000       4       0       0       0  ---p    [ anon ]
4d419000    8188       8       8       0  rwxp    [ anon ]
4dc18000       4       0       0       0  ---p    [ anon ]
4dc19000    8188      20      20       0  rwxp    [ anon ]
4e418000       4       0       0       0  ---p    [ anon ]
4e419000    8188       8       8       0  rwxp    [ anon ]
4ec18000       4       0       0       0  ---p    [ anon ]
4ec19000    8188      20      20       0  rwxp    [ anon ]
4f418000       4       0       0       0  ---p    [ anon ]
4f419000    8188       8       8       0  rwxp    [ anon ]
4fc18000       4       0       0       0  ---p    [ anon ]
4fc19000    8188      12      12       0  rwxp    [ anon ]
50480000       4       0       0       0  ---p    [ anon ]
50481000    8188      20      20       0  rwxp    [ anon ]
bef06000     132       8       8       0  rw-p  [stack]
--------  ------  ------  ------  ------
total     270064    1837     708       0
Go to the top of the page
 
+Quote Post
alx2
сообщение Nov 9 2012, 04:53
Сообщение #10


Местный
***

Группа: Участник
Сообщений: 340
Регистрация: 25-10-05
Из: Пермь, Россия
Пользователь №: 10 091



Цитата(Quasar @ Nov 7 2012, 19:29) *
Я всегда жду удаления потоков pthread_join'ом. Вывод pmap не понял.

Вот такие группы блоков памяти
Код
4f418000       4       0       0       0  ---p    [ anon ]
4f419000    8188       8       8       0  rwxp    [ anon ]

есть ни что иное как стек потока. pthread выделяет стек двумя кусочками: 4k и все остальное. Я насчитал у Вас 32 дочерних потока со стеками по 8 мегабайт у каждого. Это действительно так?
Если родительский поток вызывает pthread_join, то после завершения дочернего потока выделенная под стек память должна была освободиться.

Цитата(Quasar @ Nov 7 2012, 19:29) *
В total он пишет, что использовано 270000 KByte, у меня всего 64МБайт, что это за пространство?

Есть такое понятие как виртуальная память. Что это такое, можно почитать хотя бы тут: http://ru.wikipedia.org/wiki/Виртуальная_память
В linux пользовательские процессы работают с виртуальной памятью, а 64 Мбайта, о которых Вы пишете - это реальная физическая память. Виртуальной памяти у процесса может быть сколько угодно. Пока процесс к ней не обращается, она существует только в виде записи в таблицах.

Еще обратите внимание на поле Dirty. Если я правильно понимаю, оно показывает объем памяти, реально использованный процессом в данном блоке. Например, в процитированном мной фрагменте видно, что поток использовал 8 кбайт из 8 Мбайт, выделенных ему для стека.

Сообщение отредактировал alx2 - Nov 9 2012, 05:13


--------------------
Всего наилучшего,
Alex Mogilnikov
Go to the top of the page
 
+Quote Post
alx2
сообщение Nov 9 2012, 05:53
Сообщение #11


Местный
***

Группа: Участник
Сообщений: 340
Регистрация: 25-10-05
Из: Пермь, Россия
Пользователь №: 10 091



Цитата(alx2 @ Nov 9 2012, 09:53) *
Если родительский поток вызывает pthread_join, то после завершения дочернего потока выделенная под стек память должна была освободиться.

Небольшое уточнение. Сейчас я провел небольшой эксперимент. В моей реализации libpthread pthread_join() освобождает все стеки кроме пяти последних. Если затем создать 5 новых потоков, они повторно заюзают те блоки, которые остались после завершения предыдущих.

Вот тестовая программка, с которой можно все это увидеть:
CODE

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

void *child(void *context)
{
sleep(5);
return NULL;
}

int main()
{
// Создаем 30 потоков
pthread_t thr[30];

for(int i = 0; i < 30; i++)
pthread_create(&thr[i], NULL, child, NULL);
printf("threads created\n");

// Ждем завершения всех потоков
for(int i = 0; i < 30; i++)
pthread_join(thr[i], NULL);
printf("threads ended\n");
sleep(5);
return 0;
}

Сравните карту памяти сразу после запуска и после завершения дочерних потоков.
Попробуйте убрать pthread_join() и Вы увидите, что после завершения всех потоков вся их память остается занятой.

Сообщение отредактировал alx2 - Nov 9 2012, 05:57


--------------------
Всего наилучшего,
Alex Mogilnikov
Go to the top of the page
 
+Quote Post
Quasar
сообщение Nov 26 2012, 18:50
Сообщение #12


Местный
***

Группа: Свой
Сообщений: 257
Регистрация: 2-12-06
Из: Default City
Пользователь №: 23 021



Цитата(alx2 @ Nov 9 2012, 08:53) *
Я насчитал у Вас 32 дочерних потока со стеками по 8 мегабайт у каждого. Это действительно так?


Да, эти потоки реально существуют.

По поводу реальной и виртуальной памяти, я в общем в курсе. Я поднял этот вопрос с целью понять, не течет ли у меня память. И из обсуждения не совсем понял, как понять точно, что память течет. То есть, запустить приложения на длительный срок, просмотреть, сколько было выделено, сколько освобождено. С учетом того, что приложение не должно разрастаться по потреблению памяти со временем.
Go to the top of the page
 
+Quote Post
andrewlekar
сообщение Nov 27 2012, 04:09
Сообщение #13


Знающий
****

Группа: Участник
Сообщений: 837
Регистрация: 8-02-07
Пользователь №: 25 163



Такие утечки памяти хорошо ловятся valgrind'ом.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th June 2025 - 07:07
Рейтинг@Mail.ru


Страница сгенерированна за 0.01534 секунд с 7
ELECTRONIX ©2004-2016