
다음 C 프로그램은 하위 프로세스와 상위 프로세스 간의 경쟁 조건을 설명하는 것으로 간주됩니다.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
fork();
printf("\n 1234567890 \n");
return 0;
}
내 친구들이 그것을 실행할 때 (on우분투), 그들은 예상된 출력을 얻습니다. 이는 뒤죽박죽된 1234567890s입니다.
한 가지 예:12312345645678907890
하지만 내 컴퓨터에서 같은 프로그램을 사용해 보면아치 리눅스, 결코 그러한 출력을 제공하지 않습니다. 그것은 항상 차례로입니다.
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()
시스템 호출이나 이와 관련된 커널의 구성 요소를 다시 작성해야 할 수 있습니다.