쓰레드 자원이란?

declspec의 이미지

OS 의 자원에 대해서 몇몇 질문이 있습니다.

1. 리눅스의 pthread 나 윈도우 API 가 제공하는 쓰레드나
쓰레드를 생성 한 뒤에 쓰레드가 종료하면
JOIN 을 통해서 쓰레드 자원을 반납하는데
이때 쓰레드 자원이란 구체적으로 어떤것일까요?

2. 그리고 어차피 메인쓰레드가 종료해서 프로세스가 종료하면
해당 프로세스가 생성한 모든 쓰레드는 같이 종료되면서 모든자원이 반납되니까
프로세스가 금방 종료할 것이라면 쓰레드 자원을 반납 안해도 별 문제가 없다고 봐도 되겠죠?

3. 비슷하게 파일자원도 마찬가지로 궁금한데요
fclose 나 close 등을 이용해서 파일을 open 했던것을
close 해줘서 파일 자원을 반납하는데...
이것도 구체적으로 어떤것이 어떻게 반납되는건가요?

4. 그리고 네트웍, 파일, 쓰레드 등의 모든자원은 프로세스가 종료할때
모두 자동으로 반납이 되는거로 아는데 그렇지 않은 경우도 있나요?
(절대 불가능한지, 의도적으로만 가능한지, 어쩌다가 그렇게 되는 경우가 있는지...)

5. 커널쓰레드와 유저쓰레드의 차이가 뭔가요? pthread 는 유저쓰레드라고 알고있는데
어떤 차이가 있고 각자 어떤 용도로 사용되는지 책의 설명을 봐도 잘 모르겠는데 쉽게 예를들어
설명해주실분...

익명_사용자의 이미지

#1. Pthread의 경우,
TLS( Thread-Local Storage )가 있습니다.

http://en.wikipedia.org/wiki/Thread-local_storage

각 쓰레드 마다 갖는( 즉, 쓰레드 사이에서 공유되지 않는 )
메모리 영역이 있는데, TLS라고 불립니다.
대부분 쓰레드가 초기화 될 때, 생성되며,

만약, pthread_detach()나 pthread_join()이 호출되지 않은 경우,
해당 쓰레드가 종료 되더라도, 그 쓰레드의 TLS는 해제 되지 않습니다.

그래서, 실제로 valgrind같은 메모리 leak 검사툴로 쓰레드 사용하는 프로그램을 돌려보면
TLS가 해제 되지 않아 메모리 leak을 보여줍니다. ( join() 하지 않았을 경우 )

적어도, pthread 구현에서는 그러한 부분이 있고,
윈도우의 TLS에 대해서는 아는바가 별로 없지만, 상황은 비슷하리라 생각합니다.

#2. 네. 프로세스가 종료하면, 해당 프로세스에 종속되있던 모든 쓰레드와 자원들은 자동 해제 됩니다.
사실 이것은 쓰레드를 사용하지 않아도 해당이 됩니다.

그냥 메모리 사용하시면서, 해제 안하셔도 됩니다.
파일 열고, 안닫아도 됩니다.

어짜피, 프로세스 종료 되면 다 자동 해제 됩니다.

작은 프로그램 만들어서, 쓰레드를 생성했다가 없앴다가, 생성했다가, 없앴다가를 한 계속 반복해보세요.( join없이 )
메모리 점유율이 계속 늘어나는것을 볼수 있을것입니다.
하지만, 프로세스 종료되면 모든 메모리 leak은 다 사라집니다.

그렇게 해도 "문제가 없다고" 생각하시면
쓰레드 join()/해제 역시 문제가 없습니다.

#3. #2의 답변과 동일. 하나의 프로세스에서 최대 open가능한 descriptor의 갯수는 제한되어져있습니다.
소켓이든 파일이든 어떤 자원을 여는것은
*커널 메모리*를 소모합니다.

가령, 32bit linux 운영체제에서 cat /proc/meminfo 를 해보세요.
high-memory와 low-memory항목이 보일 것 입니다.

이중에 low-memory가 해당하는 부분이 커널 영역 메모리인데,

파일 핸들을 계속 열고 닫지 않으면, low-memory free가 계속 주는것을 보실수 있습니다.
low-memory가 바닥나면, 리눅스는 해당 프로세스를 강제로 종료시켜버립니다.

왜 low-memory란게 있고, 그런제한이 있는지에 대해 궁금하시면 운영체제 공부를 하세요.
64bit linux-kernel에서는 그러한 제한이 없습니다.
제한이 없다는 것은, 자원낭비가 없다는것이 아닙니다.
무제한 메모리 실제 한계까지 있는힘껏, 마음껏 자원낭비를 할수 있다는것입니다.

하지만, 해당 프로세스 종료되면 다 반납됩니다.
자원 낭비 마음껏 하시고, 필요없을 때, 프로세스를 종료해버리세요.

이게 "문제가 없다고" 생각하시면, 모든것은 문제가 없습니다.

#4. 프로세스에게 종속된 자원들은 프로세스가 종료될 때 반드시 수거되어야 합니다.user-space에서의
거의 모든 operation은 프로세스에 종속되어있다고 생각하면, 모두 자동반납된다고 생각해볼수도 있습니다.

아닌 경우가 있다면, 즉, 하나의 프로세스에게 종속된 자원이 아닌경우를 함 찾아보세요. 일단 생각나는것은 없네요.

#5. pthread는 유저쓰레드가 아닙니다. 커널 쓰레드도 아닙니다.
pthread자체는 POSIX에서 규정하는 thread specification입니다. 즉, 그냥 규약이자 약속이지요.

Pthread는 구현하고자 하는 사람들에게, 유저쓰레드인지 커널쓰레드인지를 강요하거나 제한하지 않습니다.

예를들어, 리눅스의 glibc pthread구현물에서는 리눅스의 커널쓰레드를
사용합니다. 리눅스 커널이 pthread가 아니라, 리눅스의 커널에서 지원하는 쓰레드 자원( 커널레벨 쓰레드 )을 이용해서

유저레벨에서 인터페이스를 구현( 쓰레드 자체를 구현한게 아니라, pthread의 interface를 구현 )
한것이 glibc pthread library입니다.

제가 커널레벨 쓰레드자원을 이용하지 않고,
순수하게 유저레벨 쓰레드만을 이용해
pthread library를 구현하면

"저의 pthread 구현물"은 유저레벨 쓰레드를 이용합니다.

하지만, pthread 라는 규약/specification 자체는 구현을 유저레벨이나 커널레벨로 제한두지 않습니다.

리눅스에서 널리 쓰이는 glibc pthread 구현물( NPTL이라고도 불리죠 )은 리눅스의 커널레벨 쓰레드를 이용하여
만들어진 user-level library입니다.( user-level thread가 아닙니다. )

=======================
커널레벨 쓰레드와 유저레벨 쓰레드의 차이에 대해서는 운영체제를 공부하세요.

jick의 이미지

경우에 따라 다른데, 어차피 곧 끝날 프로세스라면 자원낭비(?)를 맘껏 하고 프로세스를 종료해 버리는 게 올바른 방법일 수도 있습니다.

이를테면 glibc에서 메모리를 할당해 쓰면서 프로세스 종료할 때까지 반납안하는 경우가 있는데, 프로세스가 끝나기 직전에 열심히 자원 해제하고 있는 건 삽질이기 때문입니다. valgrind 도움말에 보면 이런 얘기가 있습니다.

The GNU C library (libc.so), which is used by all programs, may allocate memory for its own uses. Usually it doesn't bother to free that memory when the program ends—there would be no point, since the Linux kernel reclaims all process resources when a process exits anyway, so it would just slow things down.

The glibc authors realised that this behaviour causes leak checkers, such as Valgrind, to falsely report leaks in glibc, when a leak check is done at exit. In order to avoid this, they provided a routine called __libc_freeres specifically to make glibc release all memory it has allocated. Memcheck therefore tries to run __libc_freeres at exit.

(비슷한 얘기를 몇 년 전에도 kldp에서 했었는데 아무도 동의 안하시더군요. -_-)

kaeri17의 이미지

glibc정도 개발자들으면 당연히 알아서 하겠지만 일반 프로그램에서는 저렇게 했다가 나중에 모르고 뒤에 작업을 추가했다가 리소스를 왕창 먹는 일이 왕왕 일어날듯 합니다...

declspec의 이미지

설명덕분에 의문점들이 조금 명확해졌네요
좋은답변 감사합니다~

자기실력이 좋다고 느껴지는건 공부를 안하고 있다는 신호.

oosap의 이미지

사용중이던 자원을 명시적으로 반납하지 않고 그냥 프로세스를 종료하는 것이 위험의 정도는 몰라도 안좋은 경우는 있습니다.
TCP 소켓이 바로 그런데 단순히 close 를 통해 소켓을 종료하는 것도 지양될 수가 있죠.
종료를 깔끔하게 하기 위해서 shutdown 으로 송신 스트림으로 EOF 를 전송하고 수신 스트림으로 EOF를 받고나서 마저 수신 스트림을 shutdown 하는 경우도 있거든요.
하물며 close 도 안하고 종료한다면 상대 호스트에 대한 배려는 없는 것이죠.
이런 경우 프로세스가 종료되면서 위에 설명되어진 바 대로 close 가 불린 것과 같이 소켓이 닫히게 되겠죠. 이때 예상되는 문제는 상대 호스트가 마지막으로 전송했을지도 모를 얼마간의 데이타를 수신하지 못하게 된다는 것입니다.

이런 사례로 봐서도 자원의 반납을 명시적으로 해야만 하는 것이 존재한다는게 제 생각입니다. 그런 자원에는 주로 파일이 해당되리라 생각합니다.(소켓도 리눅스에서는 파일이므로.. 소켓 포함)

Thanks for being one of those who care for people and mankind.
I'd like to be one of those as well.

gilgil의 이미지

안 닦고 나와도 누가 뭐라 하지는 않죠. 하지만 찝찝한 기분이랄까요?

OS는 자제적으로 Process가 명시적으로 반환하지 않은 자원들(memory, mutex, thread, 각종 handle 등등...)을 파악하고 있다가 해당 process가 종료할 때, OS가 알아서 자원을 회수합니다. OS의 전통적인 기능이죠.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.