본문 바로가기

history

fork 에서 왜이럴까?

  1 #include "apue.h"
  2
  3 int glob = 6;
  4 char buf[] = "a write to stdout\n";
  5
  6
  7
  8 int main()
  9 {
 10     int var;
 11     pid_t pid;
 12
 13
 14     var = 88;
 15     if(write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1)
 16         err_sys("write error");
 17
 18     printf("before fork\n");
 19
 20     if((pid = fork()) < 0) {
 21         err_sys("fork error");
 22     }
 23     else if(pid == 0) {
 24         glob++;
 25         var++;
 26     }
 27     else {
 28         sleep(2);
 29     }
 30
 31     printf("pid = %d, glob = %d, var = %d\n", getpid(), glob, var);
 32     exit(0);
 33 }



일단 간단한 소스코드 입니다. 

./example

a write to stdout
before fork
pid = 32667, glob = 7, var = 89
pid = 32666, glob = 6, var = 88

출력결과입니다. 다들 예상하셨죠? 
이제 파일로 재지향 해보겠습니다.

./example > test.txt 
vi test.txt
  1 a write to stdout
  2 before fork
  3 pid = 32706, glob = 7, var = 89
  4 before fork
  5 pid = 32705, glob = 6, var = 88


before fork 가 두번 출력되었습니다.
버퍼링 차이 때문입니다.

write 함수는 버퍼링이 되지 않습니다   바로 출력이 되지요

write 가 fork 보다 먼저 실행되니까 당연히 한번만 출력됩니다.
표준 I/O 라이브러리는 버퍼링이 되는걸로 알고 있습니다.
여기서 표준 출력이 터미널이면 라인 버퍼링을 합니다.
그래서 정상적으로 나왔고
재지향 하여 파일로 보내면 아직 printf로 호출한 이후  버퍼에 값이 남아있습니다.
버퍼링 된 걸 fork 로 하여 모두 자식한테 복사합니다.

그래서 부모와 자식의 버퍼가 같은 상태가 됩니다.
각 각의 프로세스 가 종료되면 해당 버퍼의 복사본이 최종적으로 방출됩니다.

그럼 해결방법도 알아야 겠죠?
표준 I/O 함수를 사용시 버퍼안에 내용을 지울려면   fflush(stdout) 을 사용하면 됩니다.

뭐 다들 아시는 기초적인 내용이지만 저 같이 머리가 나쁜 경우 꼭 까먹어서.. ㅋㅋ