Apa tanggung jawab masing-masing komponen Pseudo-Terminal (PTY) (perangkat lunak, sisi master, sisi budak)?

59

Saya mencoba mencari tahu bagaimana tty bekerja 1 (alur kerja dan tanggung jawab masing-masing elemen). Saya telah membaca beberapa artikel menarik tentang itu, tetapi masih ada beberapa daerah buram.

Inilah yang saya mengerti sejauh ini:

  • Terminal yang ditiru membuat panggilan sistem yang berbeda dengan /dev/ptmx, bagian utama dari pseudo-terminal.
  • Bagian utama terminal pseudo mengalokasikan file /dev/pts/[0-N], sesuai dengan port serial yang usang, dan "menempel" terminal pseudo slave ke file tersebut.
  • Terminal pseudo slave menyimpan informasi seperti Id sesi, pekerjaan latar depan, ukuran layar.

Ini pertanyaan saya:

  1. Apakah ptmx ada tujuan selain mengalokasikan bagian slave? Apakah ini memberikan semacam "kecerdasan" , atau terminal yang ditiru (xterm misalnya) memiliki semua kecerdasan berperilaku seperti terminal?
  2. Mengapa xterm harus berinteraksi dengan bagian master, karena ia hanya meneruskan stdout dan stdin dari bagian slave? Mengapa tidak bisa langsung menulis dan membaca dari file pts ?
  3. Apakah ID sesi selalu dilampirkan ke satu file Poin dan sebaliknya? Bisakah saya mengetikkan perintah ps dan menemukan 2 sessionId untuk / dev / pts / X yang sama ?
  4. Informasi apa lagi yang ptsdisimpan toko? Apakah Xterm memperbarui semua bidang sendiri, atau apakah ptmmenambahkan "kecerdasan" di dalamnya?

1. Saya mendasarkan pemahaman saya pada TTY yang didemistifikasi oleh Linus Akesson , dan Linux Kernel oleh posting Andries Brouwer , seperti pada beberapa pertanyaan lain di situs-situs ini

Pierre-Jean
sumber

Jawaban:

58

Emulator terminal

Sisi master menggantikan garis (sepasang kabel TX / RX) yang masuk ke terminal.

Terminal menampilkan karakter yang diterima di salah satu kabel (beberapa di antaranya adalah karakter kontrol dan membuatnya melakukan hal-hal seperti memindahkan kursor, mengubah warna ...) dan mengirimkan pada kawat lain karakter yang sesuai dengan tombol yang Anda ketik.

Terminal emulator seperti xterm tidak berbeda kecuali bahwa alih-alih mengirim dan menerima karakter pada kabel, mereka membaca dan menulis karakter pada deskriptor file mereka ke sisi master. Begitu mereka telah menelurkan terminal slave, dan memulai shell Anda pada itu, mereka tidak lagi menyentuh itu. Selain meniru pasangan kawat, xterm juga dapat mengubah beberapa properti garis disiplin melalui deskriptor file ke sisi master. Misalnya, mereka dapat memperbarui atribut ukuran sehingga SIGWINCH dikirim ke aplikasi yang berinteraksi dengan slave pty untuk memberi tahu mereka tentang ukuran yang diubah.

Selain itu, ada sedikit kecerdasan di terminal / terminal emulator.

Apa yang Anda tulis ke perangkat terminal (seperti pty slave) adalah apa yang Anda maksud untuk ditampilkan di sana, apa yang Anda baca darinya adalah apa yang Anda ketikkan di sana, sehingga tidak masuk akal bagi emulator terminal untuk membaca atau menulis itu. . Mereka adalah orang-orang di ujung sana.


Garis disiplin tty

Banyak intelijen di dalam disiplin baris tty . Disiplin garis adalah modul perangkat lunak (yang berada di driver, di kernel) yang didorong di atas perangkat serial / pty yang berada di antara perangkat itu dan jalur / kabel (sisi master untuk pty).

Garis serial dapat memiliki terminal di ujung lainnya, tetapi juga mouse atau komputer lain untuk jaringan. Anda dapat melampirkan disiplin garis SLIP misalnya untuk mendapatkan antarmuka jaringan di atas perangkat serial (atau perangkat pty), atau Anda dapat memiliki disiplin garis tty . Disiplin garis tty adalah disiplin garis default setidaknya di Linux untuk perangkat serial dan pty. Di Linux, Anda dapat mengubah disiplin garis ldattach.

Anda dapat melihat efek menonaktifkan disiplin tty line dengan mengeluarkan stty raw -echo(perhatikan bahwa bash prompt atau aplikasi interaktif lainnya seperti vimengatur terminal dalam mode persis yang mereka butuhkan, jadi Anda ingin menggunakan aplikasi bodoh suka catmengalami hal itu). Kemudian, semua yang ditulis ke perangkat terminal slave membuatnya segera ke sisi master agar xterm dibaca, dan setiap karakter yang ditulis oleh xterm ke sisi master segera tersedia untuk dibaca dari perangkat slave.

Disiplin garis adalah tempat editor garis internal perangkat terminal diimplementasikan. Misalnya dengan stty icanon echo(seperti default), ketika Anda mengetik a, xterm menulis ake master, maka garis disiplin menggemakannya kembali (membuat atersedia untuk dibaca oleh xtermuntuk tampilan), tetapi tidak membuat apa pun tersedia untuk dibaca di sisi budak . Kemudian jika Anda mengetik backspace, xterm mengirim ^?atau ^Hkarakter, garis disiplin (seperti itu ^?atau ^Hsesuai dengan pengaturan erasegaris disiplin) mengirim kembali pada master ^H, spacedan ^Huntuk xtermmenghapusaAnda baru saja mengetik di layarnya dan masih tidak mengirim apa pun ke aplikasi membaca dari sisi slave, itu hanya memperbarui buffer editor baris internal untuk menghapus yang atelah Anda ketik sebelumnya.

Kemudian ketika Anda menekan Enter, xterm mengirim ^M(CR), yang diubah garis disiplin pada input ke ^ J (LF), dan mengirimkan apa yang telah Anda masukkan sejauh ini untuk membaca di sisi budak (aplikasi membaca /dev/pts/xakan menerima apa Anda mengetik termasuk LF, tetapi bukan asejak Anda menghapusnya), sementara di sisi master, ia mengirim CR dan LF untuk memindahkan kursor ke baris berikutnya dan awal layar.

Disiplin garis juga bertanggung jawab untuk mengirimkan SIGINTsinyal ke grup proses latar depan terminal ketika menerima ^Ckarakter di sisi master dll.

Banyak aplikasi terminal interaktif menonaktifkan sebagian besar fitur disiplin garis itu untuk mengimplementasikannya sendiri. Tetapi bagaimanapun juga, berhati-hatilah bahwa terminal ( xterm) memiliki sedikit keterlibatan dalam hal itu (kecuali menampilkan apa yang diperintahkan untuk ditampilkan).

Dan hanya ada satu sesi per proses dan per perangkat terminal. Sesi dapat memiliki terminal pengendali yang melekat padanya tetapi tidak harus (semua sesi dimulai tanpa terminal sampai mereka membukanya). xterm, dalam proses yang bercabang untuk mengeksekusi shell Anda biasanya akan membuat sesi baru (dan karena itu lepaskan dari terminal tempat Anda meluncurkan xtermdari jika ada), buka yang baru /dev/pts/xditelurkannya, dengan cara menyambungkan perangkat terminal itu ke sesi baru. Kemudian akan menjalankan shell Anda dalam proses itu, sehingga shell Anda akan menjadi ketua sesi. Shell Anda atau shell interaktif apa pun dalam sesi itu biasanya akan menyulap dengan kelompok proses dan tcsetpgrp(), untuk mengatur pekerjaan latar depan dan latar belakang untuk terminal itu.

Mengenai informasi apa yang disimpan oleh perangkat terminal dengan disiplin tty (serial atau pty) , itulah yang biasanya sttyditampilkan dan diubah perintah. Semua konfigurasi disiplin: ukuran layar terminal, lokal, flag input output, pengaturan untuk karakter khusus (seperti ^ C, ^ Z ...), kecepatan input dan output (tidak relevan untuk ptys). Itu sesuai dengan tcgetattr()/ tcsetattr()fungsi yang di Linux memetakan ke TCGETS/ TCSETSioctls, dan TIOCGWINSZ/ TIOCSWINSZuntuk ukuran layar. Anda mungkin berpendapat bahwa grup proses latar depan saat ini adalah informasi lain yang disimpan dalam perangkat terminal ( tcsetpgrp()/ tcgetpgrp(), TIOC{G,S}PGRPioctls), atau input atau buffer output saat ini.

Perhatikan bahwa informasi ukuran layar yang disimpan dalam perangkat terminal mungkin tidak mencerminkan kenyataan. Terminal emulator biasanya akan mengaturnya (melalui ioctl yang sama pada ukuran master) ketika jendelanya diubah ukurannya, tetapi ia dapat keluar dari sinkronisasi jika suatu aplikasi memanggil ioctl di sisi slave atau ketika ukurannya tidak ditransmisikan (dalam kasus koneksi ssh yang menyiratkan pty lain yang dihasilkan oleh sshdjika sshmengabaikan SIGWINCHmisalnya). Beberapa terminal juga dapat ditanya ukurannya melalui urutan melarikan diri, sehingga aplikasi dapat menanyakannya seperti itu, dan memperbarui disiplin garis dengan informasi itu.

Untuk lebih jelasnya, Anda dapat melihat halaman manual termiosdan tty_ioctldi Debian misalnya.

Untuk bermain dengan disiplin garis lain:

  1. Tiru mouse dengan pseudo-terminal:

    socat pty,link=mouse fifo:fifo
    sudo inputattach -msc mouse # sets the MOUSE line discipline and specifies protocol
    xinput list # see the new mouse there
    exec 3<> fifo
    printf '\207\12\0' >&3 # moves the cursor 10 pixels to the right
    

    Di atas, sisi master pty diakhiri oleh socat ke pipa bernama ( fifo). Kami menghubungkan fifo itu ke proses (shell) yang menulis 0x87 0x0a 0x00 yang berarti protokol sistem mouse no button pressed, delta(x,y) = (10,0). Di sini, kita (shell) tidak meniru terminal, tetapi mouse, 3 byte yang kami kirim tidak dapat dibaca (berpotensi diubah) oleh aplikasi dari perangkat terminal (di mouseatas adalah symlink yang dibuat oleh socatbeberapa /dev/pts/xperangkat) , tetapi harus ditafsirkan sebagai peristiwa input mouse.

  2. Buat antarmuka SLIP:

    # on hostA
    socat tcp-listen:12345,reuseaddr pty,link=interface
    # after connection from hostB:
    sudo ldattach SLIP interface
    ifconfig -a # see the new interface there
    sudo ifconfig sl0 192.168.123.1/24
    
    # on hostB
    socat -v -x pty,link=interface tcp:hostA:12345
    sudo ldattach SLIP interface
    sudo ifconfig sl0 192.168.123.2/24
    ping 192.168.123.1 # see the packets on socat output
    

    Di atas, kabel serial ditiru oleh socatsebagai soket TCP di antara hostA dan hostB. Garis disiplin SLIP menginterpretasikan byte yang dipertukarkan melalui garis virtual itu sebagai paket IP enkapsulasi SLIP untuk pengiriman pada sl0antarmuka.

Stéphane Chazelas
sumber
1
Ini jawaban terbaik. Saya menandainya sebagai benar dan menegaskannya. Bisakah Anda menambahkan bagian terakhir tentang informasi yang disimpan toko? Menurut halaman ini (bab mengkonfigurasi perangkat TTY) , pts menyimpan nilai-nilai seperti jumlah baris dan jumlah baris. Apakah mereka ada informasi lain yang disimpannya?
Pierre-Jean
@ Pierre-Jean, menambahkan info lebih lanjut.
Stéphane Chazelas
Meskipun jawaban Anda jauh dari memuaskan, akan menarik untuk melihat contoh sederhana tentang bagaimana Anda benar-benar membuat / dev / pts / M. Saya mencoba menggunakan cat /dev/ptmx &yang membuka pty baru, tetapi kemudian tidak ada proses yang dapat saya temukan terkait dengannya, jadi bagaimana Anda menggunakannya? Kedua saya mencoba echo "1" >/dev/ptmx, tetapi itu tidak berhasil ... Mengapa saya tertarik dengan ini? Karena sering menggunakan ketika seseorang terhubung dari jarak jauh melalui ssh(misalnya), Anda mendapatkan PTY allocation request failedatau No controlling tty: open /dev/ttykesalahan, yang mencegah kontrol pekerjaan. Akan lebih baik untuk lebih memahami itu.
not2qubit
@ user1147688, cara membuat pty akan menjadi pertanyaan yang berbeda. Pertanyaan ini sudah terlalu banyak. Tetapi lihat ptyhalaman manual Anda untuk detailnya.
Stéphane Chazelas
@ StéphaneChazelas Klarifikasi kecil: 1. Jadi Anda mengatakan bahwa alirannya seperti physical term---- tty---- bashpada terminal, dan pty(m)---- tty---- pty(s)---- bashpada emulator terminal? Apakah ttydisiplin bertanggung jawab untuk menggemakan karakter di terminal fisik juga? 2. Apakah program emulator terminal yang terhubung ke keyboard / layar untuk mengelola input? 3. Menurut apa yang saya pahami, Anda mengatakan bahwa buffer garis dari perintah bash / semua input terminal dilakukan oleh ttydisiplin garis alih-alih buffer I / O fungsi CI / O. Apakah ini benar?
forumulator
29

Sunting: Karena jawaban ini, saya menulis artikel khusus di blog saya, untuk orang-orang yang tertarik pada detail lebih lanjut.


Setelah banyak membaca, ini yang saya mengerti.

  • Apakah ptmx ada tujuan selain mengalokasikan bagian slave? Apakah ini memberikan semacam "kecerdasan", atau terminal yang ditiru (xterm misalnya) memiliki semua kecerdasan berperilaku seperti terminal?

    /dev/ptmxtidak mengalokasikan bagian slave : itu mengalokasikan "pseudo terminal master part". / dev / ptmx bukan terminal pseudo master : ini adalah terminal pseudo master multiplexer . Itu telah dibuat dengan standar Unix98 PTY untuk menghindari kondisi balapan ketika mengalokasikan terminal pseudo ( sumber ).

    Bagian master (ptm) terminal pseudo tidak terwakili pada sistem file. Ini diwakili oleh deskriptor file.

    Bagian slave (pts) diwakili oleh file di /dev/pts/Nmana Nadalah angka.

    The Poin diperoleh dari PTM melalui panggilan berturut-turut grandpt, unlockpt, ptsname. ( Sumber )

    PTT mengganti driver AUR yang didedikasikan untuk berkomunikasi dengan perangkat, dan edisi baris. Jadi terminal ini tidak meniru terminal tetapi menyediakan fitur edisi garis , dan menyediakan cara untuk memvisualisasikan dan berkomunikasi dengan Poin. ( Sumber )

    Berikut adalah grafik dari apa yang TTY terhubung ke perangkat keras Komunikasi TTY dengan AUR

    Dan di sini adalah grafik dari tty yang terhubung ke ptm Komunikasi TTY dengan PTM

    File ptm menangani argumen Ioctl yang berbeda (ISPTM, UNLKPT, TIOCREMOTE, TIOCSIGNAL) dari pada pts.

  • Mengapa xterm harus berinteraksi dengan bagian master, karena ia hanya meneruskan stdout dan stdin dari bagian slave? Mengapa tidak bisa langsung menulis dan membaca dari file pts?

    Proses berinteraksi dengan perangkat melalui tindakan yang dilakukan ke file virtual (baca, tulis, ioctl ..). File itu sendiri tidak ada dan driver menggunakan file untuk memicu tindakan ketika metode membaca atau menulis dipanggil. (Lihat Lampiran untuk informasi tentang driver)

    TTY mendefinisikan cara yang tepat untuk berinteraksi dengannya. Proses menulis dan membaca dari perangkat dan mengharapkan perilaku yang sama terlepas dari jenis TTY apa yang diterapkan.

    • fungsi baca digunakan oleh proses untuk membaca entri dari terminal
    • fungsi tulis digunakan oleh proses untuk mengirim output ke terminal

    Poin berperilaku seperti driver TTY. Metode baca dan tulisnya digunakan untuk mengimplementasikan perilaku Driver TTY. Karena tidak ada perangkat nyata untuk mengirim data, sepasang stream dibuat dan ptm mengimplementasikan fungsi baca untuk membaca data yang dikirim oleh pts ke stream, dan fungsi tulis untuk mengirim data ke stream yang akan tersedia kapan Poin akan membacanya.

    Ingat, file yang mewakili perangkat bukanlah file klasik, dan jika xtermingin melihat apa yang telah ditulis ke file, itu tidak bisa hanya disebut terbuka dan membacanya, karena fungsi-fungsi ini memiliki perilaku yang sama sekali berbeda di sini.

  • Apakah ID sesi selalu dilampirkan ke satu file Poin dan sebaliknya? Bisakah saya mengetikkan perintah ps dan menemukan 2 sessionId untuk / dev / pts / X yang sama?

    Saya rasa tidak, ID sesi didefinisikan oleh proses pertama yang melampirkan pts (umumnya bash), dan saya tidak melihat cara untuk membuat sesi lain dan melampirkannya ke pts yang sama. Mungkin alat seperti ini socatbisa melakukan ini?

  • Informasi lain apa yang disimpan Poin? Apakah Xterm memperbarui semua bidang sendiri, atau apakah ptm menambahkan beberapa "kecerdasan" di sana?

    Poin menyimpan 2 kategori informasi tentang terminal yang berkomunikasi dengan: the Terminfodan Termcap. Biasanya, banyak terminal emulator didasarkan pada perpustakaan yang mengelola informasi termcap untuk mereka (yang akan memberikan semua nilai kemampuan untuk meniru VTX100 misalnya). Contoh perpustakaan seperti itu adalah libvte . Sunting (lihat komentar Chazelas Stephane): Kemampuan terminal tidak disimpan oleh Poin.

Pavilyun

Pierre-Jean
sumber
termcap dan terminfo adalah database tentang kapabilitas terminal atau terminal emulator, mereka tidak ada hubungannya dengan perangkat tty atau pty.
Stéphane Chazelas
Oke, saya akan mengedit jawaban saya. Terima kasih atas komentarnya. Bisakah Anda menambahkan informasi ini tentang Poin pada jawaban Anda jika Anda mengetahuinya (ternyata Poin juga menyimpan ukuran layar, misalnya)?
Pierre-Jean
6
Ini adalah gambar yang bagus. Perangkat lunak apa yang Anda gunakan untuk membuatnya?
Gilles 'SANGAT berhenti menjadi jahat'
5
@Gilles Terima kasih. Saya melakukannya dengan Inkscape , editor grafis vektor open-source. Ini mungkin bukan cara yang paling efisien untuk melakukan grafik semacam ini, tetapi jika Anda tertarik, saya menulis artikel tentang cara membuat gambar isometrik semacam ini.
Pierre-Jean
Saya tidak berpikir Anda pernah dapat mencapai dua sesi ke terminal pengendali atau membiarkan satu sesi memiliki lebih dari satu terminal pengendali
炸鱼 薯条 德里克
9

Berikut adalah skema yang saya buat beberapa waktu lalu tentang cara sshdkerjanya. Itu tidak menyangkut pengoperasian disiplin lini dan hal-hal lain, tetapi ia menambahkan ilustrasi kehidupan nyata tentang siapa yang berinteraksi dengan apa:

masukkan deskripsi gambar di sini

Boris Burkov
sumber
terima kasih banyak atas ini. Saya menghabiskan 2 hari untuk mencari tahu. Saya hanya ingin tahu apa yang terjadi ketika tidak ada pty yang dipakai. stdin tidak ada, baik, tetapi di mana stdout dan stderr ditulis?
Bung kecil
@emmasculateur senang itu membantu Anda. Maaf, saya tidak dapat mengerti apa yang Anda maksud dengan "ketika tidak ada pty yang dipakai". Bisakah Anda memberi contoh kapan pty tidak dipakai?
Boris Burkov
1
Dengan "no pty adalah instantiated" Maksud saya ketika Anda menjalankan ssh dengan -T, yang kata orang itu menonaktifkan alokasi terminal semu. mis: ssh -T emasculateur@localhost "sleep 10" kemudian ps aux|grep sleepperlihatkan ini: emasculateur 21826 0.0 0.0 23032 3728 ? Ss 02:49 0:00 zsh -c sleep 10 Dalam kasus di mana bash menulis stdoutdan stderr? Saya harap pertanyaan saya masuk akal.
little-dude
@emmasculateur hm, ini pertanyaan yang bagus, masuk akal, saya hanya tidak memikirkannya sebelumnya. Saya kira itulah caranya, Anda memulai proses Anda sebagai daemon pada mesin jarak jauh, tanpa terminal terkait. Dugaan saya adalah input / output / error standarnya hanya /dev/nullseperti daemon normal, tetapi tidak yakin. Lihat juga: serverfault.com/questions/593399/...
Boris Burkov
@emmasculateur Saya juga menemukan kasus yang berbeda dari Anda: jika proses Anda dulunya memiliki terminal, tetapi terminal itu ditutup, proses akan menerima SIGHUP dari kernel setelah upaya baca / tulis ke stdout / stdin. Ini sering mematikan pekerjaan, dimulai melalui ssh tanpa nohupatau screen/ tmux.
Boris Burkov
0

man pts mengatakan:

File / dev / ptmx adalah file karakter dengan nomor mayor 5 dan minor 2, biasanya mode 0666 dan owner.group dari root.root. Ini digunakan untuk membuat pseudo-terminal master dan slave pair.

Ketika sebuah proses membuka / dev / ptmx, ia mendapatkan deskriptor file untuk master terminal semu (PTM), dan perangkat pseudo-terminal slave (PTS) dibuat di direktori / dev / pts. Setiap file deskriptor yang diperoleh dengan membuka / dev / ptmx adalah PTM independen dengan PTS terkait sendiri, yang jalurnya dapat ditemukan dengan meneruskan deskriptor ke ptsname (3).

Sebelum membuka pseudo-terminal slave, Anda harus melewati deskriptor file master untuk memberikan (3) dan membuka kunci (3).

Begitu master pseudo-terminal dan slave terbuka, slave menyediakan proses dengan antarmuka yang identik dengan terminal nyata.

Data yang ditulis untuk budak disajikan pada deskriptor utama sebagai input. Data yang ditulis kepada master disajikan kepada budak sebagai input.

Dalam praktiknya, pseudo-terminal digunakan untuk mengimplementasikan emulator terminal seperti xterm (1), di mana data yang dibaca dari master terminal semu ditafsirkan oleh aplikasi dengan cara yang sama dengan terminal nyata akan menginterpretasikan data, dan untuk mengimplementasikan jarak jauh program -login seperti sshd (8), di mana data membaca dari master terminal semu dikirim melintasi jaringan ke program klien yang terhubung ke terminal atau terminal emulator.

Terminal semu juga dapat digunakan untuk mengirim input ke program yang biasanya menolak untuk membaca input dari pipa (seperti su (8), dan passwd (8)).

Tentang /dev/pts/X indexing:

setiap X adalah sesi yang Anda buka, Jadi budak harus mengindeks.

Tentang TeteType (/dev/ttyN):

Itu konsol nyata telah dihasilkan oleh sistem boot Anda seperti sysV.

Tentang Mengapa budak insted master: http://commons.wikimedia.org/wiki/File:Termios-script-diagram.png

Teluk Persia
sumber
Maaf, tetapi Anda tidak menjawab pertanyaan. Saya sudah membaca halaman manual dan melihat grafik ini, tetapi perilakunya tidak jelas. Bisakah Anda, seperti yang disarankan illuminÉ, memperluas respons Anda sesuai dengan pertanyaan?
Pierre-Jean
SORRY FOR LATE
PersianGulf
Untuk menggunakan subsistem pseudo-TTY, sebuah node untuk driver sisi master / dev / ptmx dan jumlah driver slave N (N ditentukan saat instalasi) harus diinstal. Nama-nama perangkat budak adalah / dev / pts / M di mana M memiliki nilai 0 hingga N-1. Seorang pengguna mengakses perangkat pseudo-TTY melalui perangkat master (disebut ptm) yang pada gilirannya diakses melalui driver klon. Perangkat master diatur sebagai perangkat klon di mana nomor perangkat utamanya adalah yang utama untuk perangkat klon dan perangkatnya. nomor perangkat minor adalah yang utama untuk driver ptm.
PersianGulf
ya saya baca halaman pan manual ....!
PersianGulf