이 pty를 어떻게 구하고 어떻게 할 수 있나요?

이 pty를 어떻게 구하고 어떻게 할 수 있나요?

간단한 쉘 리디렉션이 /dev/ptmx새로운 의사 터미널을 제공하는 것 같습니다.

$ ls /dev/pts; ls /dev/pts </dev/ptmx
0  1  2  ptmx
0  1  2  3  ptmx

fd 선언을 소유한 프로세스가 /dev/ptmx종료되면 사라지지만 이를 유지하는 것은 간단합니다.

$ PS1='<$(ls -1 "$@" /dev/pts/*|uniq -u)> $ ' \
  exec 3<>/dev/ptmx "$0" -si -- /dev/pts/*
</dev/pts/3> $ ls /dev/pts; exec 3>&-
0  1  2  3  ptmx
<> $ ls /dev/pts; exec 3<>/dev/ptmx
0  1  2  ptmx
</dev/pts/3> $ exit

따라서 간단하게 의사 터미널을 얻는 것만으로도 충분할 것 open()같습니다 /dev/ptmx. 내 생각엔 이것이 껍질을 만들 것 같아-(또는 리디렉션을 수행하는 프로세스)- 본회사의 오너입니다.

하지만 슬레이브 측을 어떻게 할당합니까?할 수 있는슬레이브 측을 할당합니까? 그렇다면 - 그걸로 무엇을 할 수 있나요? 읽기/쓰기/새로 고침 시간에 영향을 미칠 수 있나요 stty? 참조할 때 슬레이브 측 프로세스가 내 새 pty에 연결됩니까 /dev/tty?

답변1

따라서 @muru가 주석에서 지적했듯이 셸만 사용하여 생성된 pty에 연결하는 쉬운 방법은 없는 것 같습니다. 나는 그것의 일부를 제외한 모든 것을 했습니다 unlockpt(). 내가 읽은 내용을 바탕으로여기새로 생성된 pty의 잠금을 비활성화하는 컴파일 타임 옵션이 커널에 있을 수 있지만 저는 그렇게 하고 싶지 않습니다. 그래서 저는 다른 일을 했습니다.

꼭 그럴 필요는 없어요 grantpt(). 설명에 따라 발견됨여기그것이 하는 일은 장치 파일의 UID/GID를 변경하는 것뿐입니다 /dev/pts/[num]. 하지만 man mount이 문제를 해결하는 더 쉬운 방법이 있는 것으로 알려졌습니다 . 다음은 몇 가지 devpts설치 옵션 입니다 .

  • uid=value그리고gid=value
    • 새로 생성된 PTY의 소유자 또는 그룹을 지정된 값으로 설정합니다. 아무것도 지정하지 않으면 생성 프로세스의 UID 및 GID로 설정됩니다. 예를 들어 다음이 있는 경우 단말기 GID가 5인 그룹 gid=5이면 새로 생성된 PTY가 다음 그룹에 속하게 됩니다.단말기그룹.

이것은 이미 기본적으로 내 시스템의 경우입니다. 그러나 그것을 읽은 후에 나는 결국 변화를 원할 수도 있다는 것을 깨달았습니다. 다음 섹션은 다음과 같습니다.

  • ptmxmode=value
    • 파일 시스템에서 새 ptmx 장치 노드의 모드를 설정합니다 devpts.
    • devpts여러 인스턴스에 대한 지원 (위 옵션 참조) 으로 인해 각 인스턴스에는 파일 시스템 newinstance루트에 개인 ptmx 노드가 있습니다.devpts(대개 /dev/pts/ptmx).
    • 이전 버전의 커널과의 호환성을 위해 새 ptmx 노드의 기본 모드는 입니다 0000. 이 옵션을 지정할 때 ptmxmode=value ptmx 노드에 더 유용한 모드를 지정하는 것이 좋습니다.newinstance

이렇게 하지 않고도 작동할 수 있지만 아이디어가 마음에 들어서 0640다음과 같이 설정했습니다.커널 문서. 그나저나, 커널 문서 링크에는 newinstance마운트 옵션이 자세히 설명되어 있습니다. 이는 꽤 멋지고 기본적으로 마운트별로 별도의 네임스페이스 pty 세트를 얻을 수 있게 해줍니다 /dev/ptmx.

어쨌든 그래서다른 것대부분은 다음과 같습니다:

mount -o remount,newinstance,gid=5,ptmxmode=0640 /dev/pts
mount --bind /dev/pts/ptmx /dev/ptmx

...커널 문서에서 알 수 있듯이 이유는 링크를 참조하세요. 나는 또한 내 /etc/fstab.

그리고...

<<\C cc -xc - -o pts
#include <stdio.h>
int main(int argc, char *argv[]) {
        if(unlockpt(0)) return 2;
        char *ptsname(int fd);
        printf("%s\n",ptsname(0));
        return argc - 1;
}
C

단지 작은 C 프로그램을 컴파일하고 unlockpt()stdin 호출을 시도하며, 성공하면 새로 생성되고 잠금 해제된 pty의 이름을 인쇄하고, 그렇지 않으면 stdout자동으로 2를 반환합니다.

완료되면 나만의 것을 만들 수 있습니다.거르는프로세스는 다음과 같습니다.

exec 3<>/dev/ptmx

...현재 쉘에서 기본 측면 fd를 가져온 다음...

(setsid -c "$0" -i 2>&1|tee log) <>"$(./pts <&3)" 3>&- >&0 &

이는 배경 의사 터미널의 반대편에서 대화형 쉘을 실행합니다. 인쇄된 모든 내용을 >&3사용자 입력으로 해석합니다 .

mikeserv@localhost$ echo echo hey >&3
mikeserv@localhost$ cat log
$ hey
$
mikeserv@localhost$ echo echo hey >&3
mikeserv@localhost$ cat log
$ hey
$ hey
$ 

이것은 기본적으로 백엔드, 로깅, 대화형 통역사를 제공합니다.(또는 내가 실행하고 싶은 다른 것)ala는 screen오버헤드가 많지 않으며 내가 선택한 모든 파일 설명자에서 작동합니다.

현재 쉘이 소유한 마스터 fd는 슬레이브 입력을 서비스하는 유일한 방법이며 현재 쉘 프로세스에서만 쓸 수 있습니다.(그리고 그 자식들). 쓰기를 통해 상대방과 통신할 수 >&3있고 필요에 따라 동일한 파일이나 로그 파일에서 읽을 수 있습니다.

결국 stty터미널에서 작동합니다.

mikeserv@localhost$ echo stty -a ">$(tty)" >&3
speed 38400 baud; rows 0; columns 0; line = 0;                                      
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>;
swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W;
lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc
-ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl
echoke

관련 정보