다음 C 프로그램은 하위 프로세스와 상위 프로세스 간의 경쟁 조건을 보여줍니다.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
fork();
printf("\n 1234567890 \n");
return 0;
}
내 친구가 그것을 실행하면 (우분투), 예상된 출력을 얻습니다. 이는 혼란스러운 1234567890s입니다.
한 가지 예:12312345645678907890
그런데 같은 프로그램을 내 컴퓨터에서 실행해보면아키텍처Linux, 그러한 출력을 제공하지 않습니다. 항상 차례로.
1234567890
1234567890
좋아요아치리눅스경쟁 조건을 피하는 방법이 몇 가지 있지만 제 생각에는장애를 입히다그러한 기능을 사용하고 내 친구로부터 출력을 얻고 싶습니다.
답변1
이 printf
호출은 하나 이상의 write(2)
시스템 호출을 실행하며, 처리되는 순서는 실제 출력 순서가 됩니다. 하나 이상(C 라이브러리 내의 버퍼링에 따라 다름) 라인 버퍼 출력(터미널로 이동)을 사용하면 두 번의 호출을 받을 수 있습니다 write
. 하나는 초기 개행에 대한 호출이고 다른 하나는 나머지 호출입니다.
write(1, "\n", 1);
write(1, " 1234567890 \n", 13);
호출 사이에 다른 프로세스를 예약하여 처음 두 개의 빈 줄을 제공하고 다음에는 번호가 있는 줄을 제공하는 것이 가능하지만 많은 처리가 수행되지 않으므로 제거된 시스템에서는 그럴 가능성이 없습니다.
두 프로세스 모두 정확히 동일한 내용을 인쇄하므로 한 프로세스가 다른 프로세스를 방해하지 않는 한 어떤 프로세스가 먼저 실행되는지는 중요하지 않습니다.
출력이 파일이나 파이프로 이동하는 경우 기본적으로 완전히 버퍼링되므로 프로세스당 한 번의 호출만 받을 수 write
있으며 출력을 혼합할 기회는 없습니다.
대분수의 예는 별도의 시스템 호출을 통해 숫자를 하나씩 출력하면 가능하다. 알려진 길이의 정적 문자열을 인쇄할 때 합리적인 라이브러리 구현이 왜 이런 작업을 수행하는지 이해하기 어렵습니다. 루프의 쓰기 횟수가 증가하면 혼합 출력이 발생할 가능성이 높아집니다.
이 같은:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i;
setbuf(stdout, NULL); /* explicitly unbuffered */
int x = fork();
for (i = 0 ; i < 500 ; i++) {
printf("%d", !!x);
}
if (x) {
wait(NULL);
printf("\n");
}
return 0;
}
나에게 다음과 같은 결과를 제공합니다. 이는 대부분의 경우 사실이지만 항상 그런 것은 아닙니다. 시스템은 프로세스를 예약하는 방법을 결정합니다. 예측 불가능성 때문에 우리는 일반적으로 경쟁 조건을 피하려고 노력합니다.
111111111111111111111111111111111111111111111111111111111111111111111111111
111111111111111111111111111111111111111111111111111111111111111111111111111
111100000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000010000001001100
110000000011001100110011000000010011001100110000000100110011001100000001001
100110011000000010011001100110000000100110011001100000001001100110011000000
...
답변2
fork()
시스템 호출로 인해 부모 또는 자식 프로세스가 다른 프로세스가 호출을 완료하고 printf()
문자열이 자신 의 printf()
.
상위 프로세스와 하위 프로세스 모두 동시에 루프를 실행할 시간이 있는 경우 루프에서 많은 수의 문자열을 출력하면 설명하는 혼합 출력이 표시될 수 있습니다.
문제를 "수정"하려면 fork()
시스템 호출을 다시 작성하거나 시스템 호출 내의 커널 구성 요소를 포함해야 할 수 있습니다.