Mengapa driver UART 8250 tidak membangunkan TTY jika lebih dari 256 karakter sedang menunggu?

8

Apa motivasi dari kondisi ini void serial8250_tx_chars(struct uart_8250_port *up)?

if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
    uart_write_wakeup(port);

Sudah ada sejak Linux 1.1.13 (Mei 1994) dan berulang di sebagian besar driver UART.

Latar Belakang: Linux 3.4.91 yang dikustomisasi, sistem tertanam pada ARMv7, port UART 0 dikonfigurasi untuk 38400 baud, FIFO 16 byte untuk i / o. Semua ini tidak dapat diubah di pengaturan kami.

Ketika printf-ing sangat berat pada konsol melalui UART, internal 4KB-buffer ( UART_XMIT_SIZE) mengisi dan kemudian warung proses user-space sampai buffer dikosongkan (yang membutuhkan waktu satu detik di 38.400 baud!). Kemudian perilaku ini berulang. Ini karena fungsi n_tty_write()tidur ketika buffer penuh, dan tidak terbangun untuk waktu yang lama karena kondisi yang dipertanyakan di atas.

Saya akan merasa lebih alami dan efisien jika pemeriksaan ini dihapus begitu saja. Kemudian printfs akan mengisi buffer secepat yang mereka bisa, dan kemudian melanjutkan dengan kecepatan di mana buffer sedang dikosongkan , daripada pemrosesan meledak yang saya amati.

Ini berfungsi dengan baik di lingkungan saya, tetapi tentu saja saya kehilangan atau salah paham akan sesuatu. Pasti ada alasan untuk implementasi saat ini. Apakah ada efek samping jika saya menghilangkan kondisi itu?

Sebagai pertanyaan sampingan: apakah ada opsi konfigurasi untuk menyesuaikan perilaku ini, mis. Agar printf selalu kembali segera dan membuang output jika buffer penuh?

Hans W. Heckel
sumber
Tanpa tahu terlalu banyak tentang ini, dugaan saya adalah ini: Ini adalah setup konsol serial Linux biasa. Saya bekerja dengan mereka yang menggunakan perangkat keras x86 standar. Untuk koneksi serial langsung, saya selalu harus menggunakan kontrol aliran perangkat keras. Bisa jadi ide.
vasquez
1
Kemungkinan ada perbedaan efisiensi. Mengapa tidak mengatur WAKEUP_CHARS menjadi sesuatu seperti UART_XMIT_SIZE - 128?
James Youngman
@YamesYoungman Sebenarnya, itulah yang akhirnya saya lakukan juga. Bersulang!
Hans W. Heckel

Jawaban:

2

Ini ukuran efisiensi. CPU berjalan jauh lebih cepat daripada port serial sehingga jika kernel membiarkan proses userspace berjalan setiap kali ada sedikit ruang di buffer, akhirnya akan melakukan perjalanan ke userspace dan kembali untuk setiap byte data tunggal. Itu sangat membuang waktu CPU:

$ time dd if=/dev/zero of=/dev/null bs=1 count=10000000
10000000+0 records in
10000000+0 records out
10000000 bytes (10 MB, 9.5 MiB) copied, 5.95145 s, 1.7 MB/s

real    0m5.954s
user    0m1.960s
sys     0m3.992s

$ time dd if=/dev/zero of=/dev/null bs=1000 count=10000
10000+0 records in
10000+0 records out
10000000 bytes (10 MB, 9.5 MiB) copied, 0.011041 s, 906 MB/s

real    0m0.014s
user    0m0.000s
sys     0m0.012s

Tes di atas bahkan tidak membaca dan menulis perangkat nyata: perbedaan waktu adalah seberapa sering sistem memantul antara ruang pengguna dan ruang kernel.

Jika userspace tidak ingin ditahan, ia dapat menggunakan I / O yang tidak menghalangi, atau dapat memeriksa menggunakan select()panggilan untuk melihat apakah ada ruang untuk menulis ke perangkat ... dan jika tidak, ia dapat membuang sisanya menjadi buffer sendiri dan melanjutkan pemrosesan. Memang, itu memang menyulitkan, karena sekarang Anda memiliki buffer yang harus Anda siram ... tetapi jika Anda menggunakan stdio, itu umumnya benar.

Jander
sumber
Ini mendukung komentar @James tentang efisiensi di atas. Sekarang lebih masuk akal bagi saya. Terima kasih, juga untuk angkanya!
Hans W. Heckel
Perlu dicatat bahwa sejak kernel 2.6, pertanyaan ini merujuk kode yang sering muncul di driver lapisan bawah (misalnya driver UART). Driver ini menyediakan lapisan yang lebih tinggi, serial_core, sarana untuk berinteraksi dengan perangkat keras. Ini adalah inti seri yang benar-benar berinteraksi dengan ruang pengguna (kecuali driver perangkat keras mengimplementasikan ioctls sendiri atau yang serupa). Saya percaya jawaban responden masih berlaku.
Andrew Falanga