다중쓰레드가 돌고있는 프로세스를 포크시키면 어떻게 될까..

icristi의 이미지

두 개의 쓰레드가 돌고 있는 프로세스를 포크시키면
자식 프로세스에도 두 개의 쓰레드가 돌고있는 것으로 되는건가요?

서지훈의 이미지

제가 아직 태스트는 안해봐서 잘은 모르겠지만...
개념만으로 봐선 그럴거 같네요...
child는 parent의 모든 요소를 물려 받으니깐요...
근데... 어떠한 일이 일어 날지는 테스트가 필요치 않을까요?

<어떠한 역경에도 굴하지 않는 '하양 지훈'>

#include <com.h> <C2H5OH.h> <woman.h>
do { if (com) hacking(); if (money) drinking(); if (women) loving(); } while (1);

sunshout의 이미지

제가 알기로는 어떤 스레드를 사용하는가에 따라 다른 것으로 알고 있습니다.
만약 posix pthread를 사용할 경우, 스레드를 포크하면 포크된 프로세스는 모든 스레드를 카피하는 것으로 알구 있고, 솔라리스의 그린스레드의 경우는 포크한 스레드만을 카피해서 프로세스로 만드는 것으로 알고 있습니다.

아직 테스트는 안 해본 상태이고, 공룡책(탄네바움의 운영체제)에 그렇게 나온 것으로 알고 있습니다.

Nothing will be happen.

icristi의 이미지

답변 주신 분들 감사드립니다.
제 생각에도 모든 쓰레드가 카피될 거만 같았는데 그랬었군요.

Quote:
솔라리스의 그린스레드의 경우는 포크한 스레드만을 카피해서 프로세스로 만드는 것으로 알고 있습니다.

그렇다면 리눅스에서 포크된 쓰레드만 카피해서 프로세스로 만드는 방법이 있을까요?

stoneshim의 이미지

'애벌레' 책에 설명 되었던 내용입니다.

pthread-compliant 한 implementation에서는 다음과 같습니다.
fork()를 호출한 스레드만을 포함하는 프로세스가 fork() 됩니다.
다른 스레드들은 생성되지 않습니다.

parent의 다른 스레드( fork()를 호출하지 않은 스레드) 들이 allocation한 heap도 그대로 복사됩니다.
parent의 다른 스레드가 걸어놓았던 lock이 그대로 inherit 됩니다.
이런 문제들 때문에 child process의 스레드는 dead lock에 걸릴 수 있으며 memory leak이 생길 수도 있습니다.

해결책으로 pthread_atfork() 함수가 있다고 하네요.

우리 모두 리얼리스트가 되자. 그러나 가슴에 이룰 수 없는 꿈을 가지자

icristi의 이미지

Quote:
우리 모두 리얼리스트가 되자. 그러나 가슴에 이룰 수 없는 꿈을 가지자

멋지시네요. 근데 저는 우리 모두 이상주의자가 되자. 그러나 이룰 수 있는 이상을 가지자~ 라고 하고 싶네요
stoneshim의 이미지

Quote:
근데 저는 우리 모두 이상주의자가 되자. 그러나 이룰 수 있는 이상을 가지자~ 라고 하고 싶네요

이 또한 멋진 문구군요.

감사합니다...

제 서명 문구는 체 게바라가 했던 말을 인용했습니다. 개인적으로 애착이 가는 표현입니다. ^^

우리 모두 리얼리스트가 되자. 그러나 가슴에 이룰 수 없는 꿈을 가지자

whatisid의 이미지

Quote:
'애벌레' 책에 설명 되었던 내용입니다.

그런데 애벌레 책은 뭔가요^^?

공룡책은 알겠는데, 애벌레책은 첨 보네요. 알려주십쇼~

pynoos의 이미지

참고로, 전에 GNU의 pth를 공부(?)하면서 본것을 소개하자면,
(pth는 대표적인 GNU의 user level thread library 입니다.)

pid_t pth_fork(void)
{
    pid_t pid;
    int i;

    /* run preparation handlers in LIFO order */
    for (i = pth_atfork_idx-1; i >= 0; i--)
        if (pth_atfork_list[i].prepare != NULL)
            pth_atfork_list[i].prepare(pth_atfork_list[i].arg);

    /* fork the process */
    if ((pid = pth_sc(fork)()) == -1)
        return FALSE;

    /* handle parent and child contexts */
    if (pid != 0) {
        /* Parent: */

        /* run parent handlers in FIFO order */
        for (i = 0; i <= pth_atfork_idx-1; i++)
            if (pth_atfork_list[i].parent != NULL)
                pth_atfork_list[i].parent(pth_atfork_list[i].arg);
    }
    else {
        /* Child: */

        /* kick out all threads except for the current one and the scheduler */
        pth_scheduler_drop();

        /* run child handlers in FIFO order */
        for (i = 0; i <= pth_atfork_idx-1; i++)
            if (pth_atfork_list[i].child != NULL)
                pth_atfork_list[i].child(pth_atfork_list[i].arg);
    }
    return pid;
}

이부분은 pth_fork 라는 함수로서, pth가 syscall-soft 를 지원하는 경우 fork 가 사용되는 곳에 fork 대신 define 되어 들어가는 함수 입니다.

잘보면, child 일때, pth_scheduler_drop 이 불리고, 다음에 pthread_atfork로 등록된 callback들이 불립니다.

pth_scheduler_drop 이 하는 일은,

void pth_scheduler_drop(void)
{   
    pth_t t;
    
    /* clear the new queue */
    while ((t = pth_pqueue_delmax(&pth_NQ)) != NULL)
        pth_tcb_free(t);
    pth_pqueue_init(&pth_NQ);
    
    /* clear the ready queue */
    while ((t = pth_pqueue_delmax(&pth_RQ)) != NULL)
        pth_tcb_free(t);
    pth_pqueue_init(&pth_RQ);

    /* clear the waiting queue */
    while ((t = pth_pqueue_delmax(&pth_WQ)) != NULL)
        pth_tcb_free(t);
    pth_pqueue_init(&pth_WQ);

    /* clear the suspend queue */
    while ((t = pth_pqueue_delmax(&pth_SQ)) != NULL)
        pth_tcb_free(t);
    pth_pqueue_init(&pth_SQ);

    /* clear the dead queue */
    while ((t = pth_pqueue_delmax(&pth_DQ)) != NULL)
        pth_tcb_free(t);
    pth_pqueue_init(&pth_DQ);
    return;
}   

대충 보시면, 내부에 queue들을 지우는 것인데, thread 상태별로 큐가 있는 상황입니다. 그런 thread들을 모두 제거하는 것입니다.

따라서, fork가 일어나면, fork를 부른 thread 외에 다른 thread들은 스케쥴러와 함께 바로 제거됩니다. 부른 thread도 사실 thread개념이 사라지기 때문에 main thread 로 남게 됩니다.

pth를 공부하실때는.. pth_sched.c (약 800라인) 를 뽑아다가 분석하시면, 재밌는 도움이 되실 것 같습니다.

stoneshim의 이미지

다른분들은 '애벌레'책이라고 안하시려나.. 모르겠네요.

O'Reilly 의 Pthreads Programming 입니다. ^^

우리 모두 리얼리스트가 되자. 그러나 가슴에 이룰 수 없는 꿈을 가지자

xfree의 이미지

#include <pthread.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
                                                                                                   
pid_t pid;
                                                                                                   
void *user_thread0(void *ptr)
{
        while (1) {
                printf ("pid: %d, thr: %d\n", pid, (int) pthread_self ());
                sleep (2);
        }
        return NULL;
}
                                                                                                   
void *user_thread1(void *ptr)
{
        while (1) {
                printf ("pid: %d, thr: %d\n", pid, (int) pthread_self ());
                sleep (2);
        }
        return NULL;
}
                                                                                                   
int main(int argc, char **argv)
{
        pthread_t thr1;
        pthread_t thr2;
                                                                                                   
        pthread_create (&thr1, NULL, user_thread0, NULL);
        pthread_create (&thr2, NULL, user_thread1, NULL);
                                                                                                   
        if ((pid = fork ()) == 0) {
                // child
                printf ("pid: %d, thr: %d\n", pid, (int) pthread_self ());
        } else {
                printf ("pid: %d, thr: %d\n", pid, (int) pthread_self ());
                pause ();
        }
                                                                                                   
        pthread_join (thr1, NULL);
        pthread_join (thr2, NULL);
                                                                                                   
        return 0;
}

./fork_thread
pid: 0, thr: 1082395840
pid: 0, thr: 1090784320
pid: 0, thr: 1074004608
pid: 23842, thr: 1074004608
pid: 23842, thr: 1082395840
pid: 23842, thr: 1090784320
pid: 23842, thr: 1082395840
pid: 23842, thr: 1090784320
pid: 23842, thr: 1082395840
pid: 23842, thr: 1090784320
xfree의 이미지

궁금해서 한번해보았는데요...

pynoos님 설명하신데로 자식프로세스는 쓰레드를 갖지 않았습니다. 쓰레드 생성 후 detach도 해봤는데 결과는 같았습니다.

재밌네요^^

pynoos의 이미지

아.. 참고로.. linux의 thread는 pth는 아닙니다.. 아시죠?

icristi의 이미지

pynoos wrote:
아.. 참고로.. linux의 thread는 pth는 아닙니다.. 아시죠?

이 말이 구체적으로 어떤 의미죠?
쓰레드 프로그래밍을 처음 접해봐서 잘 모르겠네요....ㅜㅡ
pth => pthread?
linux thread는 posix thread가 아니라는 말씀인가요?

그럼 어떤 thread이죠..?

서지훈의 이미지

linux thread 는 clone() 에 의한 잠깐의 눈속임 정도...
2.4까진 그런데...
NGPT 인가를 사용하면 진정한 thread를 사용할 수있다는 글을 지난번에 본거 같은데...
2.6 에선 이 기능이 추가 되었으니...
한껏 더 뛰어난 기능의 threading의 세계를 맛 볼 수가 있겠네요^^

참고: http://www.kernelnewbies.org/status/Status-02-Nov-2003.html

#include <com.h> <C2H5OH.h> <woman.h>
do { if (com) hacking(); if (money) drinking(); if (women) loving(); } while (1);

pynoos의 이미지

pth는 단지 GNU의 pthread library 이름일 뿐입니다.

http://www.gnu.org/software/pth/

icristi의 이미지

아...하! 그랬었군요...ㅜ.ㅡ
역시 내공이 육십갑자이신 분들과 대화를 하려니,
질문에 대한 답조차 감당해내기 힘드네요..흑흑
어여 내공을 쌓아야 겠습니다.

여튼 모두 감사드립니다.

서지훈의 이미지

pynoos wrote:
pth는 단지 GNU의 pthread library 이름일 뿐입니다.

http://www.gnu.org/software/pth/


이건 저도 처음보는 건데...
아... 밥벌이 하기 힘드네...
이렇게 새로운게...
하루가 다르게 계속 나오니..
가면갈수록 정보에 소외되가네...-_-ㅋ

<어떠한 역경에도 굴하지 않는 '하양 지훈'>

#include <com.h> <C2H5OH.h> <woman.h>
do { if (com) hacking(); if (money) drinking(); if (women) loving(); } while (1);

stoneshim의 이미지

Pth는 저번에 잠시 접할 기회가 있었는데...

요즘 메신저 표준프로토콜로 준비중인 XMPP를 사용하는 Jabber 서버에서 사용하더군요.
pynoos님께서 말씀하신대로 Pth는 GNU Portable Thread 이며, user-level thread를 library 로 구현한 것입니다.

저는 대충 개념만 살펴보고 넘어갔었는데... 저런 내용까지 있었군요. 대단하네요..

우리 모두 리얼리스트가 되자. 그러나 가슴에 이룰 수 없는 꿈을 가지자

방준영의 이미지

서지훈 wrote:
linux thread 는 clone() 에 의한 잠깐의 눈속임 정도...
2.4까진 그런데...
NGPT 인가를 사용하면 진정한 thread를 사용할 수있다는 글을 지난번에 본거 같은데...
2.6 에선 이 기능이 추가 되었으니...
한껏 더 뛰어난 기능의 threading의 세계를 맛 볼 수가 있겠네요^^

참고: http://www.kernelnewbies.org/status/Status-02-Nov-2003.html


NGPT는 clone() 기반 NPTL에 자리를 물려주고 퇴역했습니다. 지금은 더이상 개발이 이루어지지 않고 있죠.
서지훈의 이미지

방준영 wrote:
서지훈 wrote:
linux thread 는 clone() 에 의한 잠깐의 눈속임 정도...
2.4까진 그런데...
NGPT 인가를 사용하면 진정한 thread를 사용할 수있다는 글을 지난번에 본거 같은데...
2.6 에선 이 기능이 추가 되었으니...
한껏 더 뛰어난 기능의 threading의 세계를 맛 볼 수가 있겠네요^^

참고: http://www.kernelnewbies.org/status/Status-02-Nov-2003.html


NGPT는 clone() 기반 NPTL에 자리를 물려주고 퇴역했습니다. 지금은 더이상 개발이 이루어지지 않고 있죠.

NGPT 도 안지 몇일 안됐는데...
또 다른 NPTL 이 있었네요?
캬캬캬캬...

<어떠한 역경에도 굴하지 않는 '하양 지훈'>

#include <com.h> <C2H5OH.h> <woman.h>
do { if (com) hacking(); if (money) drinking(); if (women) loving(); } while (1);

bugiii의 이미지

소켓 프로그래밍에 pth 를 한번 적용시켜보세요. 정말 딱입니다. 제일 골치아픈 쓰레드 동기화 문제를 아주 합리적인 방법으로 해결할 수 있어서 좋았습니다. 언제 컨텍스트 전환이 일어날지 예측할 수 있다는 것만으로도 정말 행복한 작업이 될 수 있습니다.

댓글 달기

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