두 스크립트가 동일한 파일에 쓸 때 경쟁 조건이 발생하지 않습니다.

두 스크립트가 동일한 파일에 쓸 때 경쟁 조건이 발생하지 않습니다.

동일한 파일에 에코되는 두 개의 스크립트가 병렬로 실행 중입니다. 한 스크립트는 +++++++++++++++파일을 에코하고 다른 스크립트는 ===========파일을 에코합니다.

아래는 첫 번째 스크립트입니다.

#!/bin/bash
while [ 1==1 ];
do
    echo "+++++++++++++++" >> log.txt
    # commands
done

두 번째 스크립트는 다음과 같습니다.

#!/bin/bash
while [ 1==1 ];
do
    echo "===========" >> log.txt
    # commands
done

log.txt 파일은 약 1,400,000줄을 인쇄하는데, 단 한 줄도 ++== 같은 혼동되는 대문자가 없습니까?

리눅스가 이러한 혼란을 막을 수 있을까요? 그렇다면, 어떻게 그리고 왜?

답변1

간단히 말해서 이 echo명령은 write원자성 시스템 호출을 트리거합니다.

write지정된 모든 바이트가 기록된다는 보장은 없지만 이 경우(데이터가 적음)에는 기록됩니다 .

그런 다음 이론적으로 바이트 write(fd, buffer, n)보다 적게 쓰고 n프로그램이 바이트를 쓸 수 있도록 쓰여진 실제 바이트 수를 반환하는 것이 가능합니다 buffer+n.

파이프에는 무제한 용량이 없기 때문에 파이프에서 이런 일이 발생할 수 있습니다.

~에서write(2)

O_APPEND(2)를 사용하여 파일을 연 경우 파일 오프셋은 쓰기 전에 먼저 파일 끝으로 설정됩니다. 파일 오프셋 조정 및 쓰기 작업은 원자적 단계로 수행됩니다.

POSIX.1에 따르면 count가 SSIZE_MAX보다 크면 결과는 구현에 따라 정의됩니다. Linux의 상한에 대한 설명을 참조하세요.

답변2

다음 한도를 시도해 볼 수 있습니다.

#!/bin/bash                                                                                                           

outer() {
    rm log.txt
    inner() {
        a=$(perl -e 'print "'$1'"x'$2'')
        while [ 1==1 ];
        do
            echo $a >> log.txt
            # commands                                                                                                
        done
    }
    export -f inner
    timeout 5 bash -c "inner '-' $1" &
    timeout 5 bash -c "inner '+' $1" &
    wait
    sort -u log.txt
}

replace_repeats() {
    # Replace                                                                                                         
    #   ---                                                                                                           
    # with                                                                                                            
    #  -3                                                                                                             
    perl -pe 's/((.)\2+)/"$2".length$1/e'
}
# This is OK                                                                                                          
outer 10 | replace_repeats
outer 100 | replace_repeats
outer 1000 | replace_repeats
outer 4095 | replace_repeats
# This breaks.                                                                                                        
# It should give:                                                                                                     
# +4096                                                                                                               
# -4096                                                                                                               
outer 4096 | replace_repeats

관련 정보