동일한 tty에 연결될 때 zsh 설명자 10이 0/1/2와 다른 오프셋에 있는 이유는 무엇입니까? fd10을 닫고 fd0을 즉시 복사하면 영향이 있습니까? Bash에서 해당 255는 fd0/1/2와 동일한 오프셋을 가지며 이는 시스템 파일 테이블의 동일한 항목임을 나타냅니다. 그렇다면 zsh는 왜 시스템 파일 테이블에 다른 항목을 갖고 싶어합니까?
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
zsh 6980 codepoet 0u CHR 16,2 0t1266790 749 /dev/ttys002
zsh 6980 codepoet 1u CHR 16,2 0t1266790 749 /dev/ttys002
zsh 6980 codepoet 2u CHR 16,2 0t1266790 749 /dev/ttys002
zsh 6980 codepoet 10u CHR 16,2 0t3349 749 /dev/ttys002
답변1
실행하는 경우:
strace -e open,openat,fcntl,dup,dup2 zsh -f
또는 시스템의 이에 상응하는 항목을 보면 다음이 표시됩니다.
openat(AT_FDCWD, "/dev/pts/2", O_RDWR|O_NOCTTY) = 3
fcntl(3, F_DUPFD, 10) = 10
zsh가 fd 10에 대해 tty를 다시 열었습니다.
의 경우 bash --norc
다음이 표시됩니다.
dup(2) = 3
dup2(3, 255) = 255
bash의 fd255는 fd2의 복사본일 뿐입니다.
크기/오프셋은 tty 장치에 적합하지 않습니다. 이 값이 귀하의 시스템에서 무엇을 나타내는지 모르겠지만 어쨌든 둘이 다르다는 사실은 zsh로 설명할 수 있습니다. fd 10은 다른 점을 가리킵니다( 새로운)파일 설명 열기Bash에서 fd 0, 1 또는 2의 fd 255는 동일한 것을 가리킵니다.파일 설명 열기FD2와 동일합니다.
이는 실제로 큰 차이를 가져오지 않습니다.
zsh가 tty 장치를 다시 열어야 하는 이유는 다음 코드 1을 참조하세요.
/* Make sure the tty is opened read/write. */
if (isatty(0)) {
zsfree(ttystrname);
if ((ttystrname = ztrdup(ttyname(0)))) {
SHTTY = movefd(open(ttystrname, O_RDWR | O_NOCTTY));
알아채다POSIX 쉘은 stdin과 stderr이 모두 터미널로 이동하고 스크립트가 해석되지 않는 경우에만 대화형입니다..
-i 옵션이 있거나 피연산자가 없고 쉘의 표준 입력 및 표준 오류가 터미널에 추가되는 경우 쉘은 대화식으로 간주됩니다.
zsh에서는 터미널에 들어가기 위해 stderr이 필요하지 않습니다.
zsh의 fd 10(실제로 9 이상의 첫 번째 무료 fd)은 bash의 fd 255(256 미만의 첫 번째 무료 fd)와 정확히 동일하지 않습니다. zsh의 라인 편집기는 일반적으로 I/O 및 터미널 상호 작용에 사용되는 반면 bash는 AFAICT 작업 제어 작업에만 사용되며 readline
입력에는 stdin을 사용하고 입력 에코에는 stderr을 사용합니다. fd0이 읽거나 사용하기 위해 열리지 않으면 zsh는 그렇지 않습니다. 제대로 작동하지 않습니다. fd2는 쓰기용으로 열려 있지 않습니다.
1 코드는 1990년대 중반 2.5 이후에 변경되었습니다. 그때까지는 SHTTY = movefd((isatty(0)) ? dup(0) : open("/dev/tty",O_RDWR))
stdin이 터미널이 아니더라도 대화형 쉘을 갖고 해당 fd에 다른 열린 파일 설명이 없는 것이 좋습니다 . 실제로 /dev/tty
작업 제어 상호 작용의 경우 fd 0 또는 2(현재 zsh 및 bash에서 사용하는 것처럼)에서 tty를 사용하는 것보다 세션 제어 터미널에 대한 포인터를 사용하는 것이 더 정확합니다. 차이점.