stdin, stdout, stderr adalah beberapa bilangan bulat yang mengindeks ke dalam struktur data yang 'tahu' saluran I / O mana yang akan digunakan untuk proses tersebut. Saya mengerti struktur data ini unik untuk setiap proses. Apakah saluran I / O tidak lain adalah struktur susunan data dengan alokasi memori dinamis?
8
Jawaban:
Dalam Unix-seperti sistem operasi, standar input, output dan kesalahan sungai diidentifikasi oleh deskriptor file
0
,1
,2
. Di Linux, ini terlihat di bawah sistemproc
file di/proc/[pid]/fs/{0,1,2}
. File-file ini sebenarnya tautan simbolis ke perangkat pseudoterminal di bawah/dev/pts
direktori.Pseudoterminal (PTY) adalah sepasang perangkat virtual, master pseudoterminal (PTM) dan budak pseudoterminal (PTS) (secara kolektif disebut sebagai pasangan pseudoterminal ), yang menyediakan saluran IPC, agak seperti pipa dua arah antara sebuah program yang mengharapkan untuk dihubungkan ke perangkat terminal , dan program driver yang menggunakan pseudoterminal untuk mengirim input, dan menerima input dari program sebelumnya.
Poin kuncinya adalah bahwa budak pseudoterminal muncul seperti terminal biasa, misalnya ia dapat beralih antara mode noncanonical dan canonical (default), di mana ia menafsirkan karakter input tertentu, seperti menghasilkan
SIGINT
sinyal ketika karakter interupsi (biasanya dihasilkan dengan menekan Ctrl+ Cpada keyboard) ditulis ke master pseudoterminal atau menyebabkan berikutnyaread()
kembali0
ketika karakter akhir file (biasanya dihasilkan oleh Ctrl+ D) ditemukan. Operasi lain yang didukung oleh terminal menghidupkan atau mematikan gema, mengatur grup proses latar depan dll.Pseudoterminals memiliki sejumlah kegunaan:
Mereka memungkinkan program suka
ssh
mengoperasikan program berorientasi terminal pada host lain yang terhubung melalui jaringan. Program berorientasi terminal dapat berupa program apa pun, yang biasanya dijalankan dalam sesi terminal interaktif. Input standar, keluaran dan kesalahan dari program semacam itu tidak dapat dihubungkan secara langsung ke soket, karena soket tidak mendukung fungsionalitas terkait terminal yang disebutkan di atas.Mereka memungkinkan program suka
expect
menggerakkan program berorientasi terminal interaktif dari sebuah skrip.Mereka digunakan oleh emulator terminal seperti
xterm
untuk menyediakan fungsionalitas terkait terminal.Mereka digunakan oleh program-program seperti
screen
untuk multiplex terminal fisik tunggal antara beberapa proses.Mereka digunakan oleh program-program seperti
script
untuk merekam semua input dan output yang terjadi selama sesi shell.PTYs Unix98-style , digunakan di Linux, diatur sebagai berikut:
Program driver membuka master multiplexer pseudo-terminal
dev/ptmx
, di mana ia menerima deskriptor file untuk PTM, dan perangkat PTS dibuat dalam/dev/pts
direktori. Setiap deskriptor file yang diperoleh dengan membuka/dev/ptmx
adalah PTM independen dengan PTS terkaitnya sendiri.Program driver memanggil
fork()
untuk membuat proses anak, yang pada gilirannya melakukan langkah-langkah berikut:Anak memanggil
setsid()
untuk memulai sesi baru, di mana anak adalah pemimpin sesi. Ini juga menyebabkan anak kehilangan terminal pengendali .Anak melanjutkan untuk membuka perangkat PTS yang sesuai dengan PTM yang dibuat oleh program driver. Karena anak adalah pemimpin sesi, tetapi tidak memiliki terminal pengendali, PTS menjadi terminal pengendali anak.
Anak itu menggunakan
dup()
untuk menduplikasi deskriptor file untuk perangkat slave di atasnya input standar, output, dan kesalahan.Terakhir, panggilan anak
exec()
untuk memulai program berorientasi terminal yang akan terhubung ke perangkat pseudoterminal.Pada titik ini, apa pun yang ditulis oleh program driver ke PTM, muncul sebagai input untuk program berorientasi terminal pada PTS, dan sebaliknya.
Saat beroperasi dalam mode kanonik, input ke PTS buffered baris demi baris. Dengan kata lain, seperti halnya terminal reguler, program yang membaca dari PTS hanya menerima satu input ketika karakter baris baru ditulis ke PTM. Ketika kapasitas buffering habis,
write()
panggilan selanjutnya memblokir sampai beberapa input dikonsumsi.Dalam kernel Linux, file terkait panggilan sistem
open()
,read()
,write()
stat()
dll dilaksanakan di Filesystem (VFS) lapisan virtual, yang menyediakan antarmuka sistem file yang seragam untuk program userspace. VFS memungkinkan implementasi sistem file yang berbeda untuk hidup berdampingan dalam kernel. Ketika program userspace memanggil panggilan sistem yang disebutkan di atas, VFS mengalihkan panggilan ke implementasi sistem file yang sesuai.Perangkat PTS di bawah
/dev/pts
dikelola olehdevpts
implementasi sistem file yang ditentukan dalam/fs/devpts/inode.c
, sedangkan driver TTY yang menyediakanptmx
perangkat gaya Unix98 didefinisikan di dalamdrivers/tty/pty.c
.Buffer antara perangkat TTY dan disiplin garis TTY , seperti pseudoterminals, disediakan struktur buffer yang dipertahankan untuk setiap perangkat tty, yang didefinisikan dalam
include/linux/tty.h
Sebelum kernel versi 3.7, buffer adalah buffer balik :
Struktur berisi penyimpanan dibagi menjadi dua buffer ukuran yang sama. Buffer diberi nomor
0
(paruh pertamachar_buf/flag_buf
) dan1
(babak kedua). Driver menyimpan data ke buffer yang diidentifikasi olehbuf_num
. Buffer lain dapat disiram ke garis disiplin.Buffer 'dibalik' dengan beralih
buf_num
antara0
dan1
. Ketikabuf_num
diubah,char_buf_ptr
danflag_buf_ptr
diatur ke awal buffer diidentifikasi olehbuf_num
, dancount
diatur ke0
.Sejak kernel versi 3.7, buffer flip TTY telah diganti dengan objek yang dialokasikan melalui
kmalloc()
cincin yang diatur . Dalam situasi normal untuk port serial yang digerakkan IRQ dengan kecepatan tipikal, perilaku mereka hampir sama dengan flip buffer lama; dua buffer akhirnya dialokasikan dan siklus kernel di antara mereka seperti sebelumnya. Namun, ketika ada penundaan atau kecepatan meningkat, implementasi buffer baru berkinerja lebih baik karena kumpulan buffer dapat tumbuh sedikit.sumber
Dari halaman manual untuk salah satu dari ketiganya menjelaskan jawabannya:
sumber
stdin
,stdout
danstderr
dari sudut pandang pustaka C, tetapi pertanyaannya secara eksplisit tentang implementasi kernel. Saya mencoba menjelaskan sudut pandang kernel dalam jawaban saya .