fork(); 프로그램에서...

불량청년의 이미지

다름이 아니오라, fork();함수 사용에서 의문점이 있어서 그러는데요.

아래 간단한 소스를 컴파일 시키고 리다이렉트 시키면 결과과 다르게

나오는데 왜 이러는지요?

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

int global = 6;
char buf[] = "write to stdout\n";

int main(void)
{
    int var;
    pid_t pid;
    var = 55;

    if(write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1)
        perror("write error");
    printf("before fork\n");

    if((pid = fork()) < 0)
        perror("fork error");
    else if(pid == 0){
        global++;
        var++;
    }else{
        sleep(3);
    }
    printf("pid = %d, global = %d, var = %d\n", getpid(), global, var);
    exit(0);
}

$ a.out
write to stdout
before fork
pid = 450, global = 6, var = 56
pid = 449, global = 5, var = 55
그냥 실행시 이렇게 나오는데...

$ a.out > temp.out

$ more temp.out
write to stdout
before fork
pid = 450, global = 6, var = 56
before fork
pid = 449, global = 5, var = 55

"before fork"라는 내용이 두번 저렇게 나오는데... 왜그런거죠?

fork(); 호출전에 출력했던 내용이 다시 나오는거 같은데...

nangchang의 이미지

음... 예전에 이 현상에 대해서 설명을 들어는데 확실히 기억이 안나네요..

기억나는 대로 말씀 드리자면...

printf()는 바로 출력을 하는 것이 아니라 buffer에 내용을 담아 두었다가

내용을 출력합니다.

그런데 이넘의 버퍼가 비워지는 시점이 fork() 전 일 경우에는 정상적으로

1번만 출력이 됩니다만...

버퍼가 비워지기 전에 forkr()가 호출되면 버퍼의 내용까지 같이 복사가 됩니다.

따라서 후에 버퍼가 비워질때 앞서 출력되지 않은 내용이 같이 출력 되게 되므로

부모와 자식 모두에서 1번씩 출력이 되게 됩니다.

==

흠... 제가 아는건 이정돈데... 자세하게는 몰겠네요... 그럼...

불량청년의 이미지

일반적으로 write();시스템 콜은 표준I/O 라이브러리를 안쓰므로

버퍼링을 하지 않는 걸로 알고 있거든요. 고로, write(); 호출시

바로 출력되지 않는지요?

제가 만약 write(); 대신에 fputs나 기타 다른 버퍼링을 지원하는

입출력 라이브러리 함수를 사용했다면 이해가 가겠는데...

아~ 스티븐스 아저씨 책에 나오긴 나왔는데 이해가 안가네요.

혹시 write(); 호출시 데이터가 커널 버퍼에서 잠시 남아 있다가

fork(); 호출시 님 말대로 같이 데이터 영역이 복사되어서 두번 호출

되는것이 아닐런지요? :?

만약, printf(); 호출 말고 스트림 출력 함수를 쓴 후에 fflush(); 하면

저런 현상은 안나올껏도 같은데...

write(); 시스템콜에 대한 이해가 필요할꺼 같군요. ㅜㅜ;

답변 감사합니다.

H/W가 컴퓨터의 심장이라면 S/W는 컴퓨터의 영혼이다!

불량청년의 이미지

제가 책을 제대로 안봤네요. ㅜㅜ;

터미널로 리다이렉트 시키면 당연히 라인버퍼링이 되네요.

고로 저런 현상이 나타날 수 밖에 없구요. ㅡㅡ;

H/W가 컴퓨터의 심장이라면 S/W는 컴퓨터의 영혼이다!

logout의 이미지

네. fflush() 써 주셔야 합니다. :)

"I conduct to live,
I live to compose."
--- Gustav Mahler

댓글 달기

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