Страницы

Поиск по вопросам

четверг, 13 февраля 2020 г.

Освобождение ресурсов, выделенных потоку

#c #память #unix #freebsd #pthread


Всем добрый день!
Хотелось бы обсудить следующую проблему : в программе средствами библиотеки pthread
создается поток, ОС выделяет ему некоторый обьем памяти на стек и т.п., после того,
как данный поток отработал и завершился, из другого потока вызывается pthread_join(),
забирающая код возврата. При этом, не заметно, чтобы память, выделенная для данного
потока, освобождалась (при вызове pthread_create() выделилось порядка 100 кб, из которых
ничего не освободилось ни после return(), ни после pthread_join()). Кто-нибудь может
пояснить, почему? Я что-то не так делаю, или это может быть обусловлено поведением ОС ?    


Ответы

Ответ 1



@margosh, я тоже (солидарно с @mikillskegg и почти интуитивно) считаю, что память, которую брал поток, используется повторно. Иллюстрацию приведу прямо здесь. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define fatal(msg) ({perror(msg); exit(-1);}) pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; int nth = 0; void * thcli (void *a) { pthread_mutex_lock(&lock); nth--; pthread_mutex_unlock(&lock); return (void *)1; } int main (int ac, char *av[]) { int i, n = av[1]? atoi(av[1]):100; if (n < 1) n = 100; pthread_t th[n]; void *res[n]; char buf[100]; do { pthread_mutex_lock(&lock); for (i = 0; i < n; i++) { if (pthread_create (&th[i], NULL, thcli, NULL)) fatal("create"); nth++; } printf ("run %d nth = %d\n",i,nth); pthread_mutex_unlock(&lock); for (i = 0; i < n; i++) { if (pthread_join (th[i], &res[i])) fatal("join"); } printf ("join %d nth = %d\nAgain ?\n",i,nth); } while (fgets(buf,sizeof(buf),stdin), buf[0] == 'y'); exit (puts("Bye") == EOF); } Обилия инклюдов не пугайтесь, большая часть на нужны, просто скопировал для этого тестика из другой программы. А вот и иллюстация avp@avp-xub11:~/src/ig/tst$ gcc th.c -pthread ..... avp@avp-xub11:~/src/ig/tst$ ./a.out 381 create: Cannot allocate memory avp@avp-xub11:~/src/ig/tst$ ./a.out 380 run 380 nth = 380 join 380 nth = 0 Again ? y run 380 nth = 380 join 380 nth = 0 Again ? y run 380 nth = 380 join 380 nth = 0 Again ? y run 380 nth = 380 join 380 nth = 0 Again ? . Bye avp@avp-xub11:~/src/ig/tst$ ./a.out 380 run 380 nth = 380 join 380 nth = 0 Again ? y run 380 nth = 380 join 380 nth = 0 Again ? . Bye avp@avp-xub11:~/src/ig/tst$ ./a.out 381 create: Cannot allocate memory avp@avp-xub11:~/src/ig/tst$ IMHO видно, что если ресурса почти достаточно, то после завершения потоков он опять высвобождается и повторно используется (по крайней мере в такой же ситуации). UPD-1 @margosh, у меня в линуксе не растет. Добавил функцию // returns second field for last line selected by 'what' static int pri_mem (int pid, char **what) { char path[1000]; int res = 0; sprintf (path,"/proc/%d/status",pid); FILE *in = fopen(path,"r"); if (!in) { perror(path); return; } while (fgets(path,1000,in)) { char **w = what; while (*w) { if (strncasecmp(path,*w,strlen(*w)) == 0) { fputs(path,stdout); char dummy[1000]; sscanf(path,"%s %d",dummy,&res); break; } w++; } } fclose(in); return res; } и чуть изменил main(), теперь печатает память перед каждым циклом avp@avp-xub11:~/src/ig/tst$ gcc th.c -pthread avp@avp-xub11:~/src/ig/tst$ ./a.out 380 VmPeak: 2252 kB VmSize: 2252 kB VmHWM: 312 kB VmRSS: 312 kB VmStk: 136 kB run 380 nth = 380 loop 0: join 380 nth = 0 Exit ? VmPeak: 3116732 kB VmSize: 35044 kB VmHWM: 2180 kB VmRSS: 680 kB VmStk: 136 kB run 380 nth = 380 loop 1: join 380 nth = 0 Exit ? VmPeak: 3116736 kB VmSize: 35044 kB VmHWM: 2192 kB VmRSS: 692 kB VmStk: 136 kB run 380 nth = 380 loop 2: join 380 nth = 0 Exit ? VmPeak: 3116736 kB VmSize: 35044 kB VmHWM: 2192 kB VmRSS: 692 kB VmStk: 136 kB run 380 nth = 380 loop 3: join 380 nth = 0 Exit ? и дальше VmPeak: 3116736 kB VmSize: 35044 kB VmHWM: 2192 kB VmRSS: 692 kB VmStk: 136 kB run 380 nth = 380 loop 29: join 380 nth = 0 Exit ? VmPeak: 3116736 kB VmSize: 35044 kB VmHWM: 2192 kB VmRSS: 692 kB VmStk: 136 kB run 380 nth = 380 loop 30: join 380 nth = 0 Exit ? VmPeak: 3116736 kB VmSize: 35044 kB VmHWM: 2192 kB VmRSS: 692 kB VmStk: 136 kB run 380 nth = 380 loop 31: join 380 nth = 0 Exit ? y Bye avp@avp-xub11:~/src/ig/tst$ IMHO не растет. Попробуем с небольшим количеством потоков avp@avp-xub11:~/src/ig/tst$ ./a.out 30 VmPeak: 2252 kB VmSize: 2252 kB VmHWM: 316 kB VmRSS: 316 kB VmStk: 136 kB run 30 nth = 30 loop 0: join 30 nth = 0 Exit ? VmPeak: 248132 kB VmSize: 35044 kB VmHWM: 728 kB VmRSS: 628 kB VmStk: 136 kB run 30 nth = 30 loop 1: join 30 nth = 0 Exit ? VmPeak: 248136 kB VmSize: 35044 kB VmHWM: 740 kB VmRSS: 640 kB VmStk: 136 kB run 30 nth = 30 loop 2: join 30 nth = 0 Exit ? ....... ....... loop 15: join 30 nth = 0 Exit ? VmPeak: 248136 kB VmSize: 35044 kB VmHWM: 740 kB VmRSS: 640 kB VmStk: 136 kB run 30 nth = 30 loop 16: join 30 nth = 0 Exit ? VmPeak: 248136 kB VmSize: 35044 kB VmHWM: 740 kB VmRSS: 640 kB VmStk: 136 kB run 30 nth = 30 loop 17: join 30 nth = 0 Exit ? y Bye avp@avp-xub11:~/src/ig/tst$ Возможно проблема в FreeBsd.

Ответ 2



Странно, что никто не сказал про pthread_detach(). Помнится если его не запускать память выделенная под поток не освобождается и очень шустро растет, что очень заметно например в htop. Я вызываю эту штуку после pthread_create(). pthread_t restrict; if(pthread_create(&restrict, ...)) return 0; pthread_detach(restrict); return 0; "Функция pthread_join блокирует работу вызвавшей ее нити исполнения до завершения thread'а с идентификатором thread." Не вижу никакой связи с использованием памяти. Она тут не при чем.

Ответ 3



лимит комментов исчерпан. @avp, -D_THREAD_SAFE не спас. Возможно, прийдется пересмотреть логику очищения, в любом случае попробую и с detach для разнообразия, вдруг изменится чего. да, join сейчас только 1 поток делает, когда получает признак через pipe(), как Вы мне когда-то подсказали уже, за что большое спасибо :)

Комментариев нет:

Отправить комментарий