이 질문은 확장입니다.정보를 반환하기 위해 시스템 호출에 버퍼를 전달해야 하는 이유는 무엇입니까? 시스템 호출이 내부적으로 버퍼를 할당할 수 없는 이유는 무엇입니까?메모리 할당은 콜백을 시스템 호출로 전달하는 많은 동기 중 하나이기 때문입니다.
원래 시스템 호출은 버퍼에 쓰기 전에 할당할 버퍼의 크기를 알 수 있으므로 버퍼가 필요한 원래 시스템 호출의 변형에 할당 콜백을 전달하고 싶습니다.
많은 파일 시스템 API(posix/*nix뿐만 아니라 Windows/NT도 이 작업을 수행함)에서는 항상 경로 버퍼의 ax 바이트를 전달하도록 요구합니다(x는 256, 1024, 4096 또는 MAX_PATH일 수 있음). 버퍼 크기를 나타내려면 함수에 x를 전달해야 하며, 버퍼가 허용하는 것보다 더 많은 공간이 필요한 경우 함수가 실패할 수 있습니다.
시스템 호출이 사용자 공간 함수를 호출하지 못하게 하는 제한 사항이 있나요? 가능하지만 시스템 호출이 호출 사용자 공간 컨텍스트와 콜백 사용자 공간 컨텍스트를 보존해야 하기 때문에 복잡합니까? 스레드 전환 관점에서 볼 때 모든 시스템 호출은 원자성이어야 하며 시스템 호출에서 사용자 공간 코드를 호출하면 이 원자성이 손상됩니까?
답변1
시스템 호출은 커널 코드를 실행합니다. 커널은 사용자 모드 코드를 신뢰하지 않으므로 시스템 호출에 콜백이 필요한 경우 커널 모드에서 해당 콜백을 실행할 수 없습니다. 사용자 모드에서 콜백을 실행해야 합니다.
시스템 호출은 콜백이 수행할 작업을 결정할 수 없습니다. 콜백은 자체 시스템 호출을 수행할 수 있습니다. 예를 들어, 메모리를 할당하는 콜백은 프로세스에 더 많은 메모리를 제공하기 위해 sbrk
또는 같은 시스템 호출을 호출해야 할 수도 있습니다 . mmap
따라서 중첩된 시스템 호출의 실행 컨텍스트 외에도 커널은 보류 중인 시스템 호출에 대한 추가 실행 컨텍스트를 유지해야 합니다. 커널은 프로세스당 여러 실행 컨텍스트를 가질 수 있습니다. 이것이 커널 스레드의 목적입니다. 그러나 이제 일부 컨텍스트가 다른 컨텍스트 내에 중첩되어 있으므로 이러한 컨텍스트에는 추가 구조가 필요합니다.
시스템 호출이 모든 중간 정보를 프로세스에 전달하도록 함으로써 이러한 추가적인 복잡성을 피할 수 있습니다. 프로세스가 원하는 콜백 코드를 실행하도록 한 다음 준비가 되면 연속 시스템 호출을 호출합니다. 이러한 방식으로 커널은 간단한 실행 모델(시스템 호출 호출, 시스템 호출 실행, 시스템 호출 반환)을 유지하고 프로세스는 필요에 따라 콜백을 실행할 수 있습니다.
자, 여기 있습니다. 이것이 지금 작동하는 방식입니다. 프로세스는 필요한 버퍼의 크기를 쿼리하기 위해 시스템 호출을 한 다음 데이터를 얻기 위해 또 다른 시스템 호출(아마도 다른 매개변수를 가진 동일한 시스템 호출 번호)을 만들 수 있습니다.
콜백 실행 중에 데이터가 변경될 수 있다는 본질적인 어려움이 있습니다. 시스템 호출은 원자적일 필요는 없지만 주어진 순간에 시스템에 대한 일관된 보기를 제공해야 합니다. 예를 들어 프로세스가 파일에서 데이터를 읽으려고 시도할 수 있으며 콜백이 실행되는 동안 파일이 커질 수 있습니다. 커널은 콜백이 지정된 시간 내에 완료되거나 실제로 완료될 것이라고 신뢰할 수 없기 때문에 콜백이 실행되는 동안 커널은 파일 업데이트를 막을 수 없습니다. 따라서 사용자 영역 코드는 어떤 경우에도 이러한 어려움을 처리해야 합니다. 포스트 콜백 코드가 실행될 때 필요한 데이터가 더 이상 버퍼에 맞지 않을 수 있습니다.