&6과 /dev/fd/6의 차이점은 무엇입니까?

&6과 /dev/fd/6의 차이점은 무엇입니까?

파일 설명자 6을 읽으려면 <&6또는 </dev/fd/6(일명 /proc/self/fd/6)을 사용할 수 있습니다. 종종 둘 다 똑같이 효과적입니다. 그러나 해당 파일 설명자가 소켓인 경우 이상한 일이 발생합니다. 예를 들어:

$ bash -c 'ls -l /dev/fd/6;cat /dev/fd/6' 6</dev/tcp/localhost/12345
lrwx------ 1 michas michas 64 Jan 10 19:50 /dev/fd/6 -> socket:[315010]
cat: /dev/fd/6: No such device or address

이는 ls설명자가 존재함을 나타냅니다. 하지만 이런 방식으로 데이터에 접근하는 것은 불가능합니다. 사용하면 cat <&6모든 것이 정상으로 돌아갑니다.

파일 설명자에 액세스하는 두 가지 방법의 차이점은 무엇입니까?

변수에 숫자가 주어진 경우 설명자에 액세스할 수 있는 좋은 방법이 있습니까? ( </dev/fd/$fd예, 하지만 <&$fd아닙니다.)

(위 내용은 Linux에서는 볼 수 있지만 OpenBSD에서는 볼 수 없습니다. - 파일 설명자가 일반 문자 장치인 것처럼 보입니다.)

답변1

그 이유는 /dev/fd/Linux에는 소켓을 나타내는 항목에서 데이터를 읽는 구현이 없기 때문입니다.여기에서 추론에 관한 좋은 기사를 찾을 수 있습니다.따라서 해당 링크를 호출할 수 있으므로 stat로 표시되지만 ls의도적으로 비활성화됩니다.

이제 두 번째 부분으로 넘어가겠습니다. 왜 작동하나요 bash -c 'ls -l /dev/fd/6; cat <&6' 6</dev/tcp/localhost/12345? 이는 /proc파일 시스템 이 아닌 소켓/파일 API를 사용하여 소켓을 읽기 때문입니다 . 이것이 내가 관찰한 것입니다:

  1. bash터미널에서 실행 중인 인스턴스는 fd 6을 사용하여 소켓을 생성합니다.
  2. 하위 프로세스가 bash실행되고 소켓을 's' dup2(6, 0)로 연결하기 위해 호출됩니다 .catstdin
  3. dup2호출이 실패하지 않으면 cat이 읽 습니다 stdin.

다음을 통해 재현하고 관찰할 수 있습니다.

netcat -lp 12345    # in another terminal session (GNU netcat)
strace -f -e trace=open,read,write,dup2 bash -c 'ls -l /dev/fd/6; cat <&6' \
 6</dev/tcp/localhost/12345

하위 프로세스가 fd 6에 액세스할 수 있는 이유가 궁금하다면 bash파일 설명자가 여전히 존재합니다 fork.닫힘으로 표시되지 않은 경우 exec닫히지 않습니다.

답변2

귀하의 직접적인 질문에 대답하기 위해 "차이점은 무엇입니까? ":

에서 리디렉션하면 <&6셸은 dup2()시스템 호출을 사용하여 파일 설명자를 복사합니다. </dev/fd/6에서 리디렉션을 시도할 때 open().

커널은 open()에서 소켓을 지원하지 않습니다. 소켓은 장식/dev/fd 정보 용으로만 디렉토리에 나타납니다 .

관련 정보