APUE 라고
우리는 봤다원자 연산의 또 다른 예는 open 함수의 O_CREAT 및 O_EXCL 옵션을 설명할 때 발생합니다.. 이 두 옵션을 지정하면 파일이 이미 있으면 열기가 실패합니다. 또한 파일 존재 여부 확인과 파일 생성이 원자적 작업으로 수행된다고 말했습니다. 이 원자적 연산이 없으면 시도해 볼 수 있습니다.
if ((fd = open(path, O_WRONLY)) < 0) { if (errno == ENOENT) { if ((fd = creat(path, mode)) < 0) err_sys("creat error"); } else { err_sys("open error"); } }
이 문제는 파일이 open과 creat 사이의 다른 프로세스에 의해 생성된 경우 발생합니다. 이 두 함수 호출 사이에 다른 프로세스에 의해 파일이 생성되고 다른 프로세스가 파일에 무언가를 쓰는 경우 이 생성이 수행될 때 해당 데이터가 삭제됩니다. 존재 테스트와 생성을 단일 원자성 작업으로 병합하면 이 문제를 피할 수 있습니다.
시스템 호출 open()이 원자적인 경우에만 참조가 의미가 있습니까?
보다 일반적으로 Linux 또는 다른 운영 체제에서 모든 시스템은 원자적 작업을 호출합니까?
그렇지 않다면 시스템 호출이 원자성인지 어떻게 알 수 있습니까?
감사해요.
답변1
시스템 호출은 성공하거나 실패하기 때문에 일반적으로 원자적입니다. 실패하면 "롤백"을 수행하고 호출자에게 오류를 반환하는 것 외에는 아무 작업도 수행하지 않습니다. 또한 초기 상태와 최종 상태 사이의 중간 상태를 시스템에서 실행 중인 다른 스레드/프로세스에 노출하지 않으려고 노력한다는 점에서 원자적입니다. 예를 들어, 파일이 생성되었거나 존재하지 않습니다.
대부분의 경우 이러한 스레드 간(프로세스 간) 원자성은 실제로 관련이 없습니다. 호출은 open(path, O_WRONLY)
다른 스레드에서 독립적으로 실행되며 호출 스레드에서 완전히 비동기적으로 쓰기 위해 파일이 열리고 다른 스레드에서 파일에 대한 호출을 열고 닫습니다[*]. 그래서 참조의 민감도가 open
시스템 호출의 원자성에 어떻게 의존하는지 이해하지 못합니다.
[*] 동시 열기 호출이 많은 경우 커널은 물론 파일을 여는 스레드 수를 계산하는 변수와 같은 동시 업데이트로부터 자체 내부 데이터 구조를 보호해야 합니다.