이 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만으로도 의사 터미널을 얻을 수 있는 것으로 보입니다. 그게 껍질을 만들 것 같아요 -(또는 리디렉션을 수행하는 프로세스)- pty의 마스터 측 소유자입니다.

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

답변1

따라서 @muru가 주석에서 지적했듯이 쉘만으로 생성된 pty를 인터페이스하는 간단한 방법은 없는 것 같습니다. 일부만 빼고 다 관리했어요 unlockpt(). 내가 읽은 것에 따르면여기새로 생성된 pty 잠금을 비활성화하기 위한 몇 가지 컴파일 시간 옵션이 커널에 있을 수 있지만 저는 그렇게 하고 싶지 않았습니다. 그래서 저는 다른 일을 했습니다.

실제로 는 필요하지 않았습니다 grantpt(). 발견된 설명에 따르면여기/dev/pts/[num]그것이 하는 일은 장치 파일 의 UID/GID를 변경하는 것뿐입니다 . 그러나 이에 따르면 man mount이를 처리하는 더 쉬운 방법이 있습니다. 다음은 몇 가지 devpts마운트 옵션 입니다 .

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

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

  • 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

...커널 문서에서 권장하는 대로 - 이유에 대한 링크를 참조하세요. 또한 my.dll 파일에 몇 줄을 추가하여 위 명령의 효과를 영구적으로 만들었습니다 /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

이는 stdin을 호출하려고 시도하는 작은 C 프로그램을 컴파일하고 unlockpt()성공하면 새로 생성되고 잠금 해제된 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

관련 정보