fork()와 redirection in linux

mrx@Google의 이미지

#include
#include
#include

int main(int argc,char* argv[]){
pid_t pid;

printf("Hello! %d\n", getpid());

if((pid=fork())) {
waitpid(pid,0,0);
}
printf("Bye! %d\n",getpid());

return 0;
}

결과를 stdout으로 출력하면
Hello! parent id
Bye! child id
Bye! parent id
가 나오는데 다른 txt파일로 redirection 시키면
Hello! parent id
Bye! child id
Hello! parent id//추가됨
Bye! parent id
왜 Hello! parent id 가 뒤에 다시 출력 될까요? 알쏭달쏭하네요.

익명 사용자의 이미지

1. syscall은 비쌉니다.

printf 한 번 할 때마다 write syscall을 호출하는 건 정말 비싸죠.
진짜 문제는, write syscall의 비용이 실제로 쓰는 문자 수에 꼭 비례하지는 않는다는 겁니다. 고정 비용이 있죠.
따라서 c 표준 라이브러리는 대개 출력을 버퍼링하게 되어 있습니다. 출력할 데이터를 모아 뒀다가 write 한 번으로 내보내는 (flush) 것이죠.

2. c 표준 라이브러리의 버퍼링 정책은 출력이 콘솔인지 파일인지에 따라 달라집니다.

버퍼링을 언제까지고 할 수는 없으니, 사용자의 명시적인 명령(fflush)이 없더라도 어느 시점에서는 flush해야 합니다. 그 "시점"이 문제인데,

1) 콘솔 출력의 경우, 표준 라이브러리는 사용자가 실시간으로 출력을 확인하고 반응해야 한다고 생각합니다. 따라서 버퍼를 더 자주 flush합니다. 특히 개행 문자('\n')가 출력되면 버퍼를 flush하게 되죠.

2) 파일 출력의 경우, 어차피 파일에 내용이 모두 쓰인 뒤에 나중에 한번에 확인하는 경우가 많기 때문에 표준 라이브러리는 좀 더 느긋해집니다. 버퍼가 좀 더 많이 쌓인 뒤에야 flush를 한다는 말입니다.

본문의 프로그램처럼 출력되는 내용이 많지 않을 경우에는, 프로그램이 종료되기 직전쯤에야 flush될 거라고 예상할 수 있습니다.

3. 본문의 프로그램이 왜 저렇게 동작하는지는 그런 의미에서 이해할 수 있죠.

1) 콘솔 출력의 경우, fork 전의 printf 출력은 개행 문자가 끝에 있으므로 거의 바로 flush됩니다. 즉 fork 전에 stdout의 버퍼가 비워진 상태이므로 예상대로 동작합니다.

2) 파일 출력의 경우, fork 전의 printf 출력은 아직 버퍼에 남아 있는 상태입니다. fork 직후에 child는 이전에 printf 되었던 내용이 담긴 버퍼를 고스란히 복사해서 가져갑니다. 그리고 parant와 child 모두 종료되기 전에 버퍼를 flush하므로, 결국 해당 내용은 두 번 출력되는 것이죠.

4. 이런 현상을 막을 수 있는 가장 간단한 방법은, fork 직전에 fflush를 호출해서 명시적으로 버퍼를 비워 주면 됩니다.

https://en.cppreference.com/w/c/io/fflush

댓글 달기

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