Thread 생성시 Process 생성과의 관계.

litdream의 이미지

다음과 같은 코드를 실행하면, 첫번째 경우는 thread 가 부모와
같은 thread 내에서 생성되고, 두번째 경우는 부모와 다른 thread
에서 생성 됩니다..
자바에 대해서 같은 로직을 만들었을때는 thread 가 생성될때,
새로운 프로세스를 하나 달고 나가더군요..

Thread 는 Process 내에서 자원을 공유하면서 light weight 로 생성,
소멸된다고 알고있었는데, 약간 의아하더군요.. 혹시 이유를 아시는
분의 조언을 부탁드립니다.. 꾸뻑..

#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>

void* hello() {
   int i, pid;

   pid = getpid();
   printf("Thread process: %d\n", pid);

   for (i=0; i++<3; ) { 
      printf("Hello after 2 second.\n");
      fflush(stdout);
      sleep(2);
   }
   pthread_exit(NULL);
}

int main() {
   pthread_t t;
   int  rc, pid;

   pid = getpid();
   printf("Current Main process: %d\n", pid);

   rc = pthread_create(&t, NULL,(void*)hello("abcde"), NULL);   // same pid
   //rc = pthread_create(&t, NULL,hello, NULL);            // different pid

   pthread_exit(NULL);
   return 0;
}

첫번째의 결과:

$ ./a.out
Current Main process: 20359
Thread process: 20359
Hello after 2 second.
Hello after 2 second.
Hello after 2 second.

두번째의 결과

$ ./a.out
Current Main process: 20365
Thread process: 20367
Hello after 2 second.
Hello after 2 second.
Hello after 2 second.
litdream의 이미지

지금 FreeBSD 에서 테스트 해보니깐, FreeBSD 에서는 그냥 같은 Process
에서 thread 가 생기더군요.

Linux 에서만 이런현상이 나는가 싶기도 하네요.
사실은 같은 Process 에서 Thread 가 생기는것이 맞는것이라고 지금껏 믿어왔거든요.

점점 더 궁금해 집니다.. 흐흐..

삽질의 대마왕...

최종호의 이미지

   rc = pthread_create(&t, NULL,(void*)hello("abcde"), NULL);   // same pid 

이 코드는 실제로 스레드가 생성되지 않았습니다. pthread_create() 함수호출을 위해서 파라메터를 evaluate하는 단계에서 함수의 결과값을 pthread_create의 세번째 파라메터로 넘기기 위해서 hello("abcde") 함수를 호출한 것입니다.
이 함수 내에서 pthread_exit() 이 호출되었기 때문에 메인 스레드가 pthread_create()를 호출해 보기도 전에 그냥 끝나버린거죠.
새로운 스레드가 생성되지 않았기 때문에 getpid()는 메인스레드에서 수행되었고, 원pid가 리턴된 것이겠죠?

   //rc = pthread_create(&t, NULL,hello, NULL);            // different pid 

이 경우에는 새 스레드가 생성되었고, 생성된 스레드에서 hello를 수행한 것입니다.
제 시스템에서는 pthread_create()호출 후, hello에서 결과를 생성하기도 전에 메인스레드가 끝나기 때문에
올려주신 것과 같은 결과는 볼 수 없었습니다.
% uname -a
Linux hostname 2.6.9-1.3_FC2 #1 Mon Nov 15 14:46:43 EST 2004 i686 i686 i386 GNU/Linux


NPTL 이전 방식의 리눅스 시스템에서는 스레드가 내부적으로 clone() 을 통해서 구현되었고 스레드를 위해서 별도의 프로세스를 생성하는 방식을 취했습니다. 따라서 하나의 프로세스에서 여러개의 스레드를 생성하는 경우에 ps를 해보면 여러개의 프로세스 인스턴스를 볼 수 있었죠. 아마 이 방식을 사용하는 버젼의 리눅스 시스템에서 테스트하신 것이 아닌가 합니다.
litdream의 이미지

답변주신 최종호님께 인사를 먼저 드렸어야 했는데,
혼자서 열심히 삽질을 하다보니, 인사드리는걸 까먹었네요.
감사합니다.

삽질의 대마왕...

익명 사용자의 이미지

litdream님의 코드를 그대로 붙여 넣기해서
gcc를 실행하니 제 컴에서는 아래와 같은 메시지가 나오면서 컴파일이 않되는 군요.
/tmp/ccQmYXVG.o(.text+0xc0): In function `main':
: undefined reference to `pthread_create'
collect2: ld returned 1 exit status

제 컴퓨터에서 uname -a 를 실행한 결과입니다.
Linux localhost.localdomain 2.6.10-1.741_FC3smp #1 SMP Thu Jan 13 16:53:16 EST 2
005 i686 i686 i386 GNU/Linux

무엇이 문제인가요?

최종호의 이미지

Peter Bae wrote:
litdream님의 코드를 그대로 붙여 넣기해서
gcc를 실행하니 제 컴에서는 아래와 같은 메시지가 나오면서 컴파일이 않되는 군요.
/tmp/ccQmYXVG.o(.text+0xc0): In function `main':
: undefined reference to `pthread_create'
collect2: ld returned 1 exit status

제 컴퓨터에서 uname -a 를 실행한 결과입니다.
Linux localhost.localdomain 2.6.10-1.741_FC3smp #1 SMP Thu Jan 13 16:53:16 EST 2
005 i686 i686 i386 GNU/Linux

무엇이 문제인가요?

컴파일시에 -lpthread 를 붙여보세요..

익명 사용자의 이미지

그런데 왜 이렇게 복잡한거죠?
제 단순한 생각에는
#include <pthread.h>
라고 했으면
당연히 이 헤더 파일은 /usr/include/방에 있고,
관련 library는 /usr/lib/방에 있어야하고(확인해보니 실제로 있던데요)
그렇다면, 당연히 컴파일러가 알아서 찾아 링크해줘야하는 것 아닌가요?
무슨 특별한 이유가 있는 지요?

nohmad의 이미지

Peter Bae wrote:
그런데 왜 이렇게 복잡한거죠?
제 단순한 생각에는
#include <pthread.h>
라고 했으면
당연히 이 헤더 파일은 /usr/include/방에 있고,
관련 library는 /usr/lib/방에 있어야하고(확인해보니 실제로 있던데요)
그렇다면, 당연히 컴파일러가 알아서 찾아 링크해줘야하는 것 아닌가요?
무슨 특별한 이유가 있는 지요?

헤더는 전처리기에 의해 소스에 말 그대로 include 됩니다. 헤더가 하는 일이란 단순히 컴파일 과정에서 필요한 외부의 객체에 대한 기본 정보를 알려주는 일을 할 뿐이죠. 컴파일과 링킹은 독자적으로 진행되는데, 헤더는 컴파일 과정에만 필요할 뿐, 링커가 헤더에 대해 알아야 할 필요는 없습니다. 실제로 gcc의 -l 옵션은 외부의 링커(ld)를 호출합니다.

VC++에서는 C 소스에 #pragma 지시어 같은 것을 통해 링커에 대한 지시까지 가능한 것으로 아는데, VC++처럼 단일 벤더에 의해 컴파일/링킹이 통합적으로 관리되는 모델과 작은 프로세스들로 나누어 일을 처리하는 유닉스 전통 각자에 나름의 장단점이 있을 것 같습니다. 익숙해지기 나름 아닐까요? 컴파일과 링킹을 완전히 다른 프로세스로 간주하면 전혀 혼동할 필요가 없을 것 같습니다.

익명 사용자의 이미지

그러면, 표준라이브러리가 아닌 것은 꼭 -l옵션을 주고 라이브러리를 지정해주어야 하는 군요. 아무튼 너무 복잡한 것 같습니다. 사용할 함수의 라이브러리를 꼭 확인해서 지정해 주어야 하는 군요. 다시 한번 감사드립니다.

doldori의 이미지

Peter Bae wrote:
그러면, 표준라이브러리가 아닌 것은 꼭 -l옵션을 주고 라이브러리를 지정해주어야 하는 군요.

표준 라이브러리라도 UNIX 계열에서는 math.h에 있는 함수들을 쓰면 -lm을
써줘야 하더군요.
hanseok의 이미지

thread의 역사라고 해야하나? overview (?)

thread의 스케줄링 방법에서 thread를 하나의 process (스케줄링의 단위)로 볼것인가?
하나의 process 안에서 자체적으로 thread를 스케줄링 할것인가?
이런것에 대한 구현측면에서의 의견이 달리되어 있었다구 들었구요.?

또하나는 위와 같이 pid 문제인데
리눅스 커널을 보면 process/thread 모두 task 하나로 맵핑이 되어 있습니다. pid는 task id 이였구요

이런것이였기 때문에 리눅스에서 pid를 출력하면 모두 고유의 아이디가 나오도록 되어 있었습니다.

최근 버전의 리눅스 커널에서는 이것을 수정했다고 알고 있습니다.
thread 을 생성할경우 parent의 pid를 그대로 thread가 사용하는 경우입니다.
이렇게 되면 한 process에서 생성된 모든 thread는 pid가 동일하게 되는것이죠.

어떤것이 옳바른지는 생각이 다르니까?
리눅스 커널 2.4.20 이후에 동일 아이디로 바뀐것으로 알고 있는데

chage note를 보시면 그것에 대해서 나와있었던것 같은 생각이 있습니다.

==========
이것이 맞는내용이긴한데 ( 왜 적으면서 나에게 ?가 막 생기는지.)
너무 아는것이 없어서 그런것 같네요. 좀더 열심히 공부해야징.

잠이 들어야지만 꿈을 꿀수 있는것인가?
우리는 항상 꿈을 쫓아 가며 살아가는 사람들..

advanced의 이미지

hanseok wrote:
thread의 역사라고 해야하나? overview (?)
이런것이였기 때문에 리눅스에서 pid를 출력하면 모두 고유의 아이디가 나오도록 되어 있었습니다.

최근 버전의 리눅스 커널에서는 이것을 수정했다고 알고 있습니다.
thread 을 생성할경우 parent의 pid를 그대로 thread가 사용하는 경우입니다.
이렇게 되면 한 process에서 생성된 모든 thread는 pid가 동일하게 되는것이죠.

어떤것이 옳바른지는 생각이 다르니까?
리눅스 커널 2.4.20 이후에 동일 아이디로 바뀐것으로 알고 있는데

chage note를 보시면 그것에 대해서 나와있었던것 같은 생각이 있습니다.

현재 여러 운영체제들이 사용하는 thread 는 POSIX thread 인데
여기에 한 프로세스에서 생성된 스레드들의 pid 는 같아야 한다고 명시 되어 있죠

hanseok의 이미지

advanced wrote:

현재 여러 운영체제들이 사용하는 thread 는 POSIX thread 인데
여기에 한 프로세스에서 생성된 스레드들의 pid 는 같아야 한다고 명시 되어 있죠

네~~ ^^;

리눅스는 thread, process 모두 task_struct 로 나타나기 때문에 모두 다른 PID를 가지고 있었습니다.

그리고 최근엔 POSIX 표준을 따라서 위와같은 형태로 변경되어 있죠.. (시간이 많이 흐른듯하네요.. 바뀐지)

감사합니다.

잠이 들어야지만 꿈을 꿀수 있는것인가?
우리는 항상 꿈을 쫓아 가며 살아가는 사람들..

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.