Exec 전체의 파일 설명자

Exec 전체의 파일 설명자

기본적으로 파일 설명자는 exec 함수에서 열린 상태로 유지됩니다. 설명자 0-2의 경우 이 이점을 이해할 수 있습니다. 그러나 다른 설명자를 열어두는 실제 사용 사례가 있습니까? 이 사실에 의존하는 실제적인 적용이 있습니까?

답변1

실행된 명령에 fd를 전달하지 않으려면 파일 설명자에 플래그를 설정할 수 있습니다( open(): O_CLOEXEC 이상: FD_CLOEXEC).fcntl()

명령을 실행하려면 내부 파일 설명자를 사용하여 수행해야 하는 작업입니다.

예를 들어, 쉘에서는 다음과 ksh93같은 작업을 수행합니다. exec 3< some-file다른 쉘이나 fd를 사용하여 연 경우 fd:를 원하지 않거나 액세스하지 않으려면 { cmd1; cmd2; } 3< file수동으로 닫아야 합니다 .cmd1cmd2{cmd1 3<&-; cmd2; } 3< file이는 좋은 습관이지만 일반적으로 따르지 않아도 문제가 되지 않으므로 항상 따르지는 않습니다..

자, 이 기능이 유용할까요? 예, 여러 명령이 이에 의존합니다.

일부 명령은 호출자가 열었던 파일 설명자를 인수로 사용합니다. 마음속에 떠오르는 몇 가지 예는 다음과 같습니다.

  • xterm그리고 그 -S옵션
  • qemu여러가지 일을 위해
  • flock(발신자 fd의 파일을 잠급니다)
  • 명령 은 옵션 test이라고도 합니다 ( 요즘 대부분의 Bourne과 유사한 쉘에 유틸리티가 내장되어 있지만 여전히 실행할 수 있는 명령이 있습니다 ).[-ttesttest
  • dialog사용자 입력, 사용자 출력 및 오류, 호출자의 입력 및 출력에는 파일 설명자가 필요하므로 이를 위해 추가 fd를 사용할 수 있습니다.
  • gpg또는 openssl암호나 기타 정보를 전달하기 위해 파일 설명자를 지정할 수 있습니다.

많이있다돕는 사람유틸리티(예:구현하다아마도 이에 의존하는 setuid/setgid 실행 파일을 사용하여 다른 사용자 또는 그룹으로 실행되는 명령의 일부일 수 있습니다.

프로세스 교체는 이에 따라 달라집니다.

에서는 diff <(cmd1) <(cmd2)2개의 파일 설명자(파이프에 대한)가 diff에 전달되고 diff인수로 전달된 특수 /dev/fd/n을 통해 이를 열어 액세스합니다.

프로세스 교체가 없는 셸의 경우 다음을 수동으로 수행할 수 있습니다.

cm1 | { cmd2 | diff /dev/fd/3 -; } 3<&0

답변2

TinyMUSH와 아마도 많은 형제 및 하위 코드 라이브러리는 exec의 이 기능을 사용하여 큰 효과를 냅니다. 서버를 다시 시작하는 명령을 실행하여 사용자 연결을 유지하면서 새로운 바이너리로 업그레이드할 수 있습니다.

이는 파일 설명자를 포함하여 연결된 각 사용자에 대한 정보가 포함된 작은 데이터베이스를 작성하여 수행됩니다. TinyMUSH의 새로 실행된 복사본은 재시작 데이터베이스를 읽어 연결된 사용자에 대한 지식을 복원하고 중단된 부분부터 계속됩니다.

최종 결과: 새로운 기능이 출시되고 사용자에게는 짧은 일시 중지만 표시됩니다.

Nginx가 수행하는 작업은 연결을 끊지 않고 바이너리 업그레이드를 수행하는 것과 다소 유사합니다.

답변3

연결된 소켓은 이런 방식으로 하위 프로세스에 전달될 수 있습니다. 예를 들어 들어오는 연결을 수락하는 네트워크 서버는 해당 연결 처리를 완전히 다른 프로세스에 전달할 수 있습니다.

보다inetd 소스 코드, 일반적인 예를 들어 보겠습니다.

답변4

나는 설명자 2 이외의 것을 전달할 수 있는 진정한 보편적인 프로그램이 없다고 생각합니다. 그렇다면 exec()된 프로그램은 하드 코딩된 파일 설명자 번호를 가정해야 합니다.

write(3, ...);

또는

fp = fdopen(3, "r");

이것은 나쁜 코딩 습관입니다. 부모와 자식 프로그램을 엄격하게 통제하고 다른 사람이 간섭할 수 없는 경우에만 의미가 있습니다.

관련 정보