상위 및 하위 프로세스에서 사용되는 파일

상위 및 하위 프로세스에서 사용되는 파일
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>


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


    FILE *fptr;
    pid_t pid;

    fptr = fopen("Shared File.txt", "a");
    pid = fork();

    if( pid > 0 ){ // parent process

        int counter = 0;

        while( counter < 10 ){
            fprintf(fptr, "a");
            ++counter;
        }
        wait(NULL);
    }
    else{

        int counter = 0;

        while( counter < 5 ){
            fprintf(fptr, "b");
            ++counter;
        }
    }

    return 0;
}

이 코드를 실행하면 코드에 의해 생성된 파일에 다음 메시지가 포함됩니다. bbbbbaaaaaaaaaa

이 코드를 실행할 때마다 동일한 메시지가 나타납니다. 쓰기 파일을 섞인 순서로 처리하지 않는 이유는 무엇입니까?

운영 체제가 처음에 하위 프로세스를 종료하려고 하는 이유는 무엇입니까?

메시지에 대한 나의 기대는 다음과 같습니다. 프로세스 간 지속적인 전환이 없는 baabbaaabaaabaa입니다.

답변1

아버지와 아들 사이의 일정은 (적어도)자식 프로세스가 실행될 때그리고포크 시스템 호출은 어떻게 작동하나요?.

하지만 이 경우에도 일반 파일에 쓰기를 stdio사용하고 있습니다 . fprintf()기본적으로 stdio시스템 호출 오버헤드를 절약할 만큼 충분한 데이터가 기록될 때까지 출력은 일반 파일로 버퍼링됩니다. x86 Linux에서는 일반적으로 4096바이트 청크로 작성하는 것처럼 보이지만 버퍼링을 수동으로 설정하지 않으면 이를 기대할 수 없습니다(참조setbuf()그리고 친구들).

strace프로그램에서 수행한 시스템 호출 표시와 같은 명령을 사용하여 이를 확인할 수 있습니다.

따라서 어떤 프로세스가 먼저 실행될지 예측할 수 없지만 이 경우 s가 a연속적으로 기록되고 bs도 기록된다는 것을 예측할 수 있습니다. 당신은 bbbbbaaaaaaaaaa또는 중 하나만 얻을 수 있으며 aaaaaaaaaabbbbb, 어느 것을 얻는지는 거의 운의 문제입니다.

답변2

나는 기본적으로 @ikkachu에 동의합니다.

당신이 얻을 것 bbbbbaaaaaaaaaa또는 aaaaaaaaaabbbbb예측할 수 있는 것. 운영 체제는 하위 프로세스가 완료될 때까지 기다린 wait(NULL)다음 상위 프로세스가 종료됩니다. 종료 시 버퍼가 플러시되면 하위 프로세스가 먼저 쓰기를 시작합니다.

그러나 예측 가능한 버퍼에 의존하지 마십시오. 필요한 경우 명시적 새로 고침을 사용하세요.

답변3

사용자 ilkkachu는 버퍼링이 출력에 어떤 영향을 미치는지에 대해 잘 설명했습니다. 내 대답은 버퍼링을 제거하면(예: fprintf호출을 pair 로 대체하면 어떻게 되는지 설명합니다 . 이 경우 s 와 s 가 write엄격하게 교대로 표시됩니다 . 이는 쌍에 대한 호출로 인해 일정이 변경되기 때문입니다. 하나의 프로세스에 작성하면 프로세스가 블록된 다음 해당 차례를 전달합니다. 다른 프로세스로 이동하는 등의 작업을 수행합니다.abwrite

write를 호출하면 어떤 일이 일어날지 상상해 봅시다.아니요막혔습니다. 그런 다음 시간 척도를 고려해야 합니다. 최신 프로세서는 초당 수십억 개의 명령을 실행할 수 있지만 예약 빈도는 일반적으로 100Hz에서 1000 사이이므로 한 번에 한두 개가 아닌 s a및 s의 실행 시간을 얻게 됩니다. b헤르츠. 프로세스는 선점되고 다른 프로세스가 실행되도록 예약되기 전에 최대 수천만 개의 명령을 실행할 수 있습니다. 시스템 호출 오버헤드를 고려하더라도 이는 연속된 as 또는 bs의 매우 긴 문자열을 인쇄하는 데 프로세스 시간을 제공합니다.

답변4

ikkachu와 Johan은 자신이 하는 행동을 관찰하는 이유를 아주 잘 설명했기 때문에 각 프로세스가 스트림을 플러시하고 잠시 휴면 상태가 되도록 프로그램을 약간 다시 작성했습니다(각 스레드가 매번 다른 방식으로 시차를 두고 기회를 얻도록). 엇갈린 효과를 더 명확하게 확인하세요.

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

int main(void) {
  FILE *fptr = stdout;
  pid_t pid;
  int counter = 0;

  pid = fork();

  if(pid > 0) { // parent process
    while(counter++ < 10) {
      fprintf(fptr, "aa");
      fflush(fptr);
      sleep(1);
    }
    wait(NULL);
    puts("");
  } else {
    while(counter++ < 5) {
      fprintf(fptr, "bbbb");
      fflush(fptr);
      sleep(1);
    }
  }
}

여러 번 실행하면 때때로 다른 결과가 나타납니다.

~ $ ./thread
aabbbbaabbbbaabbbbaabbbbaabbbbaaaaaaaaaa
~ $ ./thread
aabbbbaabbbbaabbbbaabbbbaabbbbaaaaaaaaaa
~ $ ./thread
aabbbbaabbbbaabbbbaabbbbbbbbaaaaaaaaaaaa
~ $ ./thread
aabbbbaabbbbaabbbbaabbbbaabbbbaaaaaaaaaa

관련 정보