프로세스 대체를 사용하지 않고 다중 출력 파이프와 같은 작업을 수행하기 위해 이를 사용하는 몇 가지 질문이 있습니다.
이를 위해 고정 fd 번호를 사용하는 것이 안전합니까? 프로그램이 이미 설명된 대로 이를 사용하고 있을 가능성이 있습니까?여기중요한 내용을 다룰 것인가, 아니면 관련 없는 내용을 읽을 것인가?
답변1
프로그램에서 이미 사용하고 있을 가능성이 있나요?
습관. 프로그램이나 스크립트가 시작되기 전에 I/O 리디렉션이 발생합니다.
일반적으로 프로그램이나 스크립트가 시작되면 표준 설명자(0/표준 입력, 1/표준 출력, 2/표준 오류)만 열립니다. (터미널, 장치, 파일 또는 네트워크 소켓을 참조할 수 있지만 열려 있어야 합니다. 하나를 "닫는" 대신 원치 않는 설명자를 / 에서 로 /dev/null
, 본질적으로 "Nowhere"/"Nothing" 으로 리디렉션합니다.)
open
프로그램은 자유 설명자 와 마찬가지로 시스템 호출을 통해 설명자를 사용합니다 . 즉, 파일이나 소켓을 열 때 커널이 필요하지 않습니다.특정 설명자에게, 커널 선택 설명자. 따라서 프로그램이 추가 설명자를 사용하는 유일한 시간은 프로그램이 시작될 때 열릴 것으로 예상되는 시간입니다. 이와 같은 드문 유틸리티 데몬이 있습니다. 표준 설명자 외에도 설명자 3이 시작 시 열려 있으면 관리 서비스(또는 이와 유사한 것)에 연결될 것으로 기대합니다.
프로그램이 하드코딩된 설명자를 사용하기로 결정한 경우(유일한 이유는 다른 프로그램을 포크하고 실행하기 때문입니다)예상하다설명자는 열려야 합니다. 제가 말했듯이 이것은 매우 드뭅니다. 이미 열려 있는 설명자는 프로그램이 해당 목적으로 대체할 때 닫힙니다. (그런데 프로그램이 POSIXy 시스템과 같이 특정 설명자를 사용하려고 한다고 나타낼 때 커널은 종료를 수행합니다. dup2()
프로세스는 신경 쓸 필요가 없습니다.)
쉘 스크립트(Bash 및 sh)는 고정된 설명자 번호를 사용하므로 스크립트는 특정 입력/출력 리디렉션을 수행하기 위해 특정 설명자를 사용할 수 있습니다. 그러나 이런 일이 발생하면 스크립트는 설명자가 닫혀 있다고 가정하므로 이전 리디렉션이 무시되고 아무런 효과가 없습니다. (설명자가 열려 있고 스크립트가 일부 내부 항목에 해당 설명자를 사용하는 경우 스크립트가 이를 리디렉션할 때 원래 설명자는 이전 단락에서 언급한 이유로 커널에 의해 먼저 닫힙니다. 모든 유형의 경우 데이터 유출이 발생하려면 스크립트를 구체적으로 작성해야 합니다.시험설명자가 이미 열려 있고피하다리디렉션하세요. )
또한 Fortran I/O 장치나 채널은 둘 다 숫자로 식별되더라도 설명자와 아무 관련이 없습니다. 따라서 Fortran 프로그램이 단위 10을 사용하더라도 설명자 10을 사용한다는 의미는 아닙니다.
이를 위해 고정 fd 번호를 사용하는 것이 안전합니까?
예. POSIX는 프로그램이 최소 20개의 설명자를 열 수 있도록 지정하므로 3에서 19 사이의 고정 숫자는 모두 잘 작동합니다.
핵심은 이를 잘 문서화하는 것입니다. 가급적이면 스크립트 시작 부분(스크립트의 경우)에 간단한 설명을 두거나 사용법( -h
또는 --help
명령줄 옵션) 및 매뉴얼 페이지(프로그램의 경우)에 기록하는 것이 좋습니다.
스크립트의 경우 충돌이 발생하면(이 경우 위에서 언급한 것처럼 "프로그램이 시작되자마자 파이프가 닫히기 때문에 스크립트가 전혀 작동하지 않습니다"가 됩니다.) 사용자가 고정 설명자 번호를 변경할 수 있다고 가정할 수 있습니다. 그들의 요구를 더 잘 충족시키기 위해. 따라서 스크립트 작성자로서 귀하의 임무는 미리 계획을 세우고 다음 사람들이 더 쉽게 계획할 수 있도록 하는 것입니다. (의도와 전반적인 디자인을 설명하는 명확한 설명이면 충분합니다. 설명자 번호를 변수에 설정하거나 스크립트가 수행하는 모든 작은 작업을 설명할 필요가 없습니다.)
프로그램이 런타임 구성이 가능하도록 만드는 것은 좋은 생각입니다. 예를 들어, 그래픽 사용자 인터페이스가 있는 특수 제어 프로토콜에 대해 프로그램/데몬이 설명자 3(켜져 있는 경우)을 사용하도록 할 수 있습니다. 그러나 특정 명령줄 옵션(예: "-c 5")에서는 명명된 설명자 문자를 사용합니다. (또는 -c /dev/name
지정된 파일, 명명된 파이프 또는 로컬 도메인 소켓을 사용 -c named-pipe
하거나 사용) -c :socketpath
이 방법으로 사용자는 스크립트와의 충돌을 쉽게 해결할 수 있습니다.