zsh가 연 파일 설명자가 1씩 감소하는 이유는 무엇입니까?

zsh가 연 파일 설명자가 1씩 감소하는 이유는 무엇입니까?

일반적인 방법으로 파일 설명자를 명시적으로 열 수 있습니다.

$ ls -lh /dev/fd/
total 0
lrwx------ 1 tavianator users 64 Jul 10 11:06 0 -> /dev/pts/6
lrwx------ 1 tavianator users 64 Jul 10 11:06 1 -> /dev/pts/6
lrwx------ 1 tavianator users 64 Jul 10 11:06 2 -> /dev/pts/6
lr-x------ 1 tavianator users 64 Jul 10 11:06 3 -> /proc/31288/fd
$ exec 3<foo
$ ls -lh /dev/fd/
total 0
lrwx------ 1 tavianator users 64 Jul 10 11:07 0 -> /dev/pts/6
lrwx------ 1 tavianator users 64 Jul 10 11:07 1 -> /dev/pts/6
lrwx------ 1 tavianator users 64 Jul 10 11:07 2 -> /dev/pts/6
lr-x------ 1 tavianator users 64 Jul 10 11:07 3 -> /home/tavianator/foo
lr-x------ 1 tavianator users 64 Jul 10 11:07 4 -> /proc/31334/fd

여태까지는 그런대로 잘됐다. zsh두 자리 파일 설명자 구문은 지원되지 않는 것 같지만 10<foo변수 대체 구문은 지원합니다 {fd}<foo.

$ fd=10
$ exec {fd}<foo
$ ls -lh /dev/fd/
total 0
lrwx------ 1 tavianator users 64 Jul 10 11:08 0 -> /dev/pts/6
lrwx------ 1 tavianator users 64 Jul 10 11:08 1 -> /dev/pts/6
lr-x------ 1 tavianator users 64 Jul 10 11:08 11 -> /home/tavianator/foo
lrwx------ 1 tavianator users 64 Jul 10 11:08 2 -> /dev/pts/6
lr-x------ 1 tavianator users 64 Jul 10 11:08 3 -> /home/tavianator/foo
lr-x------ 1 tavianator users 64 Jul 10 11:08 4 -> /proc/31413/fd

그런데 잠깐, 왜 fd야?11대신에 열다10?

답변1

그것이 ZSH가 작성된 방식이기 때문입니다. 기본적으로 ZSH는 파일 설명자를 fd 10에 복사합니다.

$ PS1='%% ' zsh -f
% lsof -p $$ | grep 10u
zsh     29192 jhqdoe   10u   CHR  136,0       0t0         3 /dev/pts/0
% 

Src/exec.c후속 호출의 fd 관련 코드movefd

/**/
static void
addfd(int forked, int *save, struct multio **mfds, int fd1, int fd2, int rflag,
      char *varid)
{
    int pipes[2];

    if (varid) {
        /* fd will be over 10, don't touch mfds */
        fd1 = movefd(fd2);
        if (fd1 == -1) {
            zerr("cannot moved fd %d: %e", fd2, errno);
            return;

다음으로 Src/utils.c사용 가능한 10개 이상은 이미 기본적으로 취해진 것이므로 첫 번째로 볼 수 있는 것은 11개 항목을 반복합니다.

movefd(int fd)
{
    if(fd != -1 && fd < 10) {
#ifdef F_DUPFD
        int fe = fcntl(fd, F_DUPFD, 10);
#else
        int fe = movefd(dup(fd));
#endif

zsh기준은 코드 경로를 strace사용하고 있지만 zsh는 기본적으로 해당 번호에 중복을 저장하기 때문에 11에서 시작하는 새 fd를 사용할 수 없다는 의견이 있습니다 .fcntlfcntl(...movefd(dup(...

이 모든 {somelabel}작업은 10보다 큰 사용 가능한 가장 낮은 파일 설명자를 얻는 것입니다. 이는 쉘이 열려 있는 다른 항목에 따라 11이거나 더 높은 숫자일 수 있습니다.

% exec {foo}>asdf
% echo $foo
11
% exec {quer}>asdf
% echo $quer
12
...

관련 정보