Pemacu kernel Linux ialah salah satu komponen terpenting dalam sistem Linux. Mereka bertanggungjawab untuk berkomunikasi dengan peranti perkakasan supaya sistem pengendalian dapat mengenal pasti dan menggunakan perkakasan dengan betul. Walau bagaimanapun, membangunkan pemacu kernel Linux bukanlah satu tugas yang mudah. Dalam artikel ini, kami akan menyelidiki kaedah pelaksanaan pemacu kernel Linux dan memberikan pembaca pemahaman dan bimbingan yang komprehensif.
Dalam pemacu Linux, lapisan bawah pemacu USB ialah perkakasan pengawal hos USB yang berjalan di atasnya ialah pemacu pengawal hos USB Di atas pengawal hos ialah lapisan teras USB, dan lapisan atas ialah pemacu peranti USB lapisan ( Masukkan cakera U, tetikus, USB ke port bersiri dan pemacu peranti lain pada hos).
Oleh itu, dalam hierarki bahagian hos, pemacu USB yang akan dilaksanakan merangkumi dua kategori: Pemacu pengawal hos USB dan pemacu peranti USB yang pertama mengawal peranti USB yang dimasukkan ke dalamnya, dan yang kedua mengawal cara peranti USB berkomunikasi dengan tuan rumah. Teras USB kernel Linux bertanggungjawab untuk kerja utama pengurusan pemacu USB dan pemprosesan protokol. Teras USB antara pemacu pengawal hos dan pemacu peranti adalah sangat penting Fungsinya termasuk: dengan mentakrifkan beberapa struktur data, makro dan fungsi, ia menyediakan antara muka pengaturcaraan untuk pemacu peranti ke atas dan menyediakan antara muka pengaturcaraan untuk pengawal hos USB. pemandu ke bawah; Pembolehubah global mengekalkan maklumat peranti USB bagi keseluruhan sistem kawalan palam panas peranti, kawalan penghantaran data bas, dsb.
Pemandu sisi peranti USB dalam kernel Linux dibahagikan kepada tiga peringkat: pemacu UDC, API Alat dan pemacu Alat. Pemacu UDC mengakses perkakasan secara langsung, mengawal komunikasi asas antara peranti USB dan hos, dan menyediakan fungsi panggil balik untuk operasi berkaitan perkakasan ke lapisan atas. API Alat semasa ialah pembalut ringkas di sekeliling fungsi panggil balik pemacu UDC. Pemacu Alat secara khusus mengawal pelaksanaan fungsi peranti USB, membenarkan peranti memaparkan ciri-ciri seperti "sambungan rangkaian", "pencetak" atau "Penyimpanan Massa USB Ia menggunakan API Alat untuk mengawal UDC untuk melaksanakan fungsi di atas". API Alat mengasingkan pemacu UDC lapisan bawah daripada pemacu Alat lapisan atas, membenarkan pelaksanaan fungsi dipisahkan daripada komunikasi asas apabila menulis pemacu sisi peranti USB dalam sistem Linux.
Penerangan ringkas tentang empat peringkat ini adalah seperti berikut:
Peranti biasanya mempunyai satu atau lebih konfigurasi
Konfigurasi selalunya mempunyai satu atau lebih antara muka
Antara muka tidak mempunyai atau lebih daripada satu titik akhir
4 Bentuk komunikasi USB yang paling asas ialah melalui titik akhir (titik akhir USB dibahagikan kepada empat jenis: Sampukan, Pukal, ISO dan Kawalan, setiap satu dengan kegunaan berbeza), titik akhir USB hanya boleh menghantar data dalam satu arah, dari hos ke peranti atau dari peranti ke hos Titik akhir boleh dianggap sebagai paip sehala. Pemacu mendaftarkan objek pemacu dengan subsistem USB dan kemudian menggunakan pengilang dan pengenalan peranti untuk menentukan sama ada perkakasan telah dipasang. Teras USB menggunakan senarai (struktur yang mengandungi ID pengilang dan ID peranti) untuk menentukan pemacu yang hendak digunakan untuk peranti, dan skrip palam panas menggunakan ini untuk menentukan apabila peranti tertentu dipalamkan ke dalam sistem secara automatik dilaksanakan.
1) Peranti USB: struktur data yang sepadan struct usb_device
2) Konfigurasi: struct usb_host_config (Hanya satu konfigurasi boleh berkuat kuasa pada bila-bila masa)
3) Antara muka USB: struct usb_interface (Teras USB menghantarnya kepada pemacu peranti USB, dan pemacu peranti USB bertanggungjawab untuk kawalan seterusnya. Antara muka USB mewakili fungsi asas, dan setiap pemacu USB mengawal antara muka. Jadi fizikal Peranti perkakasan mungkin memerlukan lebih daripada satu pemandu )
.4) Endpoint: struct usb_host_endpoint, maklumat titik akhir sebenar yang terkandung dalam struktur lain: struct usb_endpoint_descriptor (deskriptor titik akhir, mengandungi semua data khusus USB).
Bentuk komunikasi USB yang paling asas ialah melalui sesuatu yang dipanggil titik akhir. Titik akhir USB hanya boleh memindahkan data dalam satu arah (dari hos ke peranti (dipanggil titik akhir output) atau dari peranti ke hos (dipanggil titik akhir input)). Titik akhir boleh dianggap sebagai paip sehala.
Terdapat 4 jenis titik akhir USB yang berbeza, masing-masing dengan kaedah penghantaran data yang berbeza:
1) KAWALAN
Titik akhir kawalan digunakan untuk mengawal akses kepada bahagian peranti USB yang berbeza Ia biasanya digunakan untuk mengkonfigurasi peranti, mendapatkan maklumat peranti, menghantar arahan kepada peranti atau mendapatkan laporan status peranti. Titik akhir ini biasanya lebih kecil. Setiap peranti USB mempunyai titik akhir kawalan yang dipanggil "Titik Akhir 0", yang digunakan oleh teras USB untuk mengkonfigurasi peranti apabila dipalamkan. Protokol USB memastikan bahawa jalur lebar sentiasa mencukupi untuk titik akhir kawalan menghantar data ke peranti.
2) MENGGANGGU
Setiap kali hos USB meminta data daripada peranti, titik akhir gangguan menghantar sejumlah kecil data pada kadar tetap. Ini ialah kaedah pemindahan data utama untuk papan kekunci dan tetikus USB. Ia juga digunakan untuk memindahkan data ke peranti USB untuk mengawal peranti. Biasanya tidak digunakan untuk memindahkan sejumlah besar data. Protokol USB memastikan bahawa jalur lebar sentiasa mencukupi untuk titik akhir gangguan menghantar data ke peranti.
3) Batch PUKAL
Titik akhir pukal digunakan untuk memindahkan sejumlah besar data. Titik akhir ini biasanya jauh lebih besar daripada titik akhir gangguan Ia biasanya digunakan dalam situasi yang tidak boleh berlaku sebarang kehilangan data. Protokol USB tidak menjamin bahawa pemindahan akan diselesaikan dalam tempoh masa tertentu. Jika tidak ada ruang yang cukup pada bas untuk menghantar keseluruhan paket PUKAL, ia dibahagikan kepada beberapa paket untuk penghantaran. Titik akhir ini biasanya digunakan pada pencetak, Storan Massa USB dan peranti rangkaian USB.
4) ISOCHRONOUS
Titik akhir isokron juga memindahkan sejumlah besar data dalam kelompok, tetapi data ini tidak dijamin untuk dihantar. Titik akhir ini digunakan dalam peranti yang boleh mengendalikan kehilangan data dan lebih bergantung pada mengekalkan aliran data yang berterusan. Seperti peralatan audio dan video dan sebagainya.
Kawalan dan titik akhir kelompok digunakan untuk pemindahan data tak segerak, manakala titik akhir gangguan dan isokron adalah berkala. Ini bermakna titik akhir ini disediakan untuk menghantar data secara berterusan pada masa yang tetap, dan teras USB menyimpan lebar jalur yang sepadan untuknya.
struct usb_host_endpoint{ struct usb_endpoint_descriptor desc;//端点描述符 struct list_head urb_list;//此端点的URB对列,由USB核心维护 void *hcpriv; struct ep_device *ep_dev; /* For sysfs info */ unsigned char*extra;/* Extra descriptors */ int extralen; int enabled;};
Pemandu peranti USB berkomunikasi dengan semua peranti USB melalui urb. urb diterangkan oleh struktur struktur urb (termasuk/linux/usb.h).
urb menghantar atau menerima data secara tak segerak ke titik akhir tertentu peranti USB tertentu. Pemacu peranti USB boleh menetapkan berbilang urb kepada satu titik akhir atau menggunakan semula satu urb untuk berbilang titik akhir yang berbeza, bergantung pada keperluan pemandu. Setiap titik akhir dalam peranti mengendalikan baris gilir urb, jadi berbilang urb boleh dihantar ke titik akhir yang sama sebelum baris gilir dikosongkan.
Kitaran hidup tipikal urb adalah seperti berikut:
(2) Titik akhir khusus yang diberikan kepada peranti USB tertentu
(3) Diserahkan kepada teras USB
(4) Dihantar oleh teras USB kepada pemacu pengawal hos USB khusus untuk peranti tertentu
(5) Diproses oleh pemacu pengawal hos USB dan dihantar ke peranti
(6) Selepas operasi di atas selesai, pemacu pengawal hos USB memberitahu pemacu peranti USB.
urb juga boleh dibatalkan pada bila-bila masa oleh pemandu yang menyerahkannya; jika peranti dikeluarkan, urb boleh dibatalkan oleh teras USB. urbs dicipta secara dinamik dan mengandungi kiraan rujukan dalaman supaya ia boleh dikeluarkan secara automatik apabila pengguna terakhir mengeluarkannya.
8.1 Hantar urb
Setelah urb dibuat dan dimulakan dengan betul, ia boleh diserahkan ke teras USB untuk dihantar ke peranti USB Ini dicapai dengan memanggil fungsi sb_submit_urb.
int usb_submit_urb(struct urb *urb, gfp_t mem_flags);
Parameter:
struct urb *urb: penunjuk ke urb yang diserahkan
gfp_t mem_flags: Gunakan parameter yang sama yang dihantar ke panggilan kmalloc untuk memberitahu teras USB cara memperuntukkan penimbal memori tepat pada masanya
Oleh kerana fungsi usb_submit_urb boleh dipanggil pada bila-bila masa (termasuk dari konteks gangguan), pembolehubah mem_flags mesti ditetapkan dengan betul Bergantung pada masa usb_submit_urb dipanggil, hanya 3 nilai yang sah tersedia:
GFP_ATOMIC
Nilai ini harus digunakan selagi syarat berikut dipenuhi:
1) Pemanggil berada dalam pengendali hujung urb, pengendali sampukan, bahagian bawah, tasklet atau fungsi panggil balik pemasa.
2) Pemanggil memegang kunci putaran atau kunci baca-tulis Ambil perhatian bahawa jika semaphore sedang dipegang, nilai ini tidak diperlukan.
3) semasa->keadaan bukan TASK_RUNNING Melainkan pemandu telah menukar keadaan semasa dengan sendirinya, keadaan hendaklah sentiasa TASK_RUNNING.
GFP_NOIO
Pemacu digunakan semasa pemprosesan blok I/O Ia juga harus digunakan semasa pengendalian ralat untuk semua jenis storan.
GFP_KERNEL
Semua situasi lain yang tidak termasuk dalam situasi yang dinyatakan sebelum ini
Selepas urb berjaya diserahkan ke teras USB, tiada ahli struktur urb boleh diakses sehingga fungsi rutin pemprosesan akhir dipanggil
8.2 rutin pemprosesan urb end
Jika usb_submit_urb berjaya dipanggil dan memindahkan kawalan urb ke teras USB, fungsi mengembalikan 0 jika tidak, kod ralat negatif dikembalikan Jika fungsi berjaya dipanggil, rutin pengendali akhir akan dipanggil sekali apabila urb ditamatkan .Apabila fungsi ini dipanggil, teras USB melengkapkan urb dan mengembalikan kawalannya kepada pemacu peranti.
Hanya ada 3 situasi untuk menamatkan urb dan memanggil rutin pemprosesan tamat:
(1)urb berjaya dihantar ke peranti dan peranti mengembalikan pengesahan yang betul Jika ya, pembolehubah status dalam urb ditetapkan kepada 0.
(2) Ralat berlaku, dan nilai ralat direkodkan dalam pembolehubah status dalam struktur urb.
(3)URB nyahpaut daripada teras USB Ini berlaku sama ada apabila pemandu memberitahu teras USB untuk membatalkan urb yang diserahkan dengan memanggil usb_unlink_urb atau usb_kill_urb, atau apabila urb telah diserahkan kepadanya dan peranti dialih keluar daripada sistem.
Dalam struktur usb_driver struct, terdapat 2 fungsi yang dipanggil teras USB pada masa yang sesuai:
(1) Apabila peranti dipalamkan, jika teras USB berpendapat bahawa pemacu boleh mengendalikannya (teras USB menggunakan senarai (struktur yang mengandungi ID pengilang dan ID nombor peranti) untuk menentukan pemacu yang hendak digunakan untuk peranti) , fungsi kuar dipanggil Fungsi kuar menyemak maklumat peranti yang dihantar kepadanya dan menentukan sama ada pemandu sebenarnya sesuai untuk peranti ini.
(2) Atas sebab tertentu, apabila peranti dialih keluar atau pemandu tidak lagi mengawal peranti, hubungi fungsi putus sambungan dan lakukan pembersihan yang sesuai.
Kedua-dua fungsi pengesanan dan pemutusan sambungan dipanggil dalam konteks utas kernel hab USB, jadi adalah sah untuk mereka tidur Untuk memendekkan masa pengesanan USB, kebanyakan kerja dilakukan apabila peranti dihidupkan mungkin. Ini kerana teras USB berada dalam satu Penambahan dan pengalihan keluar peranti USB dikendalikan dalam benang, jadi mana-mana pemacu peranti perlahan boleh menjadikan masa pengesanan peranti USB lebih lama.
9.1 Analisis fungsi pengesanan
Dalam fungsi panggil balik siasatan, pemacu peranti USB harus memulakan mana-mana struktur tempatan yang mungkin digunakan untuk mengurus peranti USB dan menyimpan semua maklumat peranti yang diperlukan ke struktur tempatan, kerana ia biasanya lebih mudah untuk melakukan ini pada masa ini untuk berkomunikasi dengan peranti, pemacu USB Biasanya menyiasat alamat titik akhir peranti dan saiz penimbal.
Dalam artikel ini, kami memperkenalkan kaedah pelaksanaan pemacu kernel Linux secara terperinci, termasuk rangka kerja pemacu kernel, penulisan modul kernel, pendaftaran pemacu peranti dan penyahdaftaran, dsb. Kami percaya bahawa melalui mengkaji artikel ini, pembaca boleh mempunyai pemahaman yang lebih mendalam tentang prinsip pelaksanaan pemacu kernel Linux dan memberikan lebih banyak rujukan dan bantuan untuk kerja pembangunan mereka sendiri.
Atas ialah kandungan terperinci Penjelasan terperinci tentang aliran kerja pemacu USB Linux. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!