Rumah > Artikel > Tutorial sistem > Linux Intermediate - "Pemandu" Pengetahuan peringkat rendah yang mesti dipelajari untuk mengawal perkakasan
Pacu kesedaran
Pemandu merangkum operasi peranti perkakasan asas dan menyediakan antara muka fungsi ke lapisan atas.
Klasifikasi peranti: Sistem Linux membahagikan peranti kepada 3 kategori: Peranti aksara, peranti sekat dan peranti rangkaian.
Mari kita berikan contoh untuk menerangkan keseluruhan proses panggilan
open("/dev/pin4",O_RDWR);
dan panggil pin4 di bawah /dev untuk membukanya dengan cara yang boleh dibaca dan boleh ditulis **== Apabila lapisan atas dibuka dipanggil ke kernel, gangguan lembut akan berlaku. Nombor gangguan ialah 0X80, yang dimasukkan dari ruang kernel==**system_call
(fungsi kernel), dan system_call akan mengetahui nombor peranti yang anda inginkan berdasarkan nama peranti /dev/pin4. sys_open
dalam VFS, sys_open akan ditemui dalam senarai pemandu, dan cari pemandu berdasarkan nombor peranti utama dan nombor peranti kecil Fungsi terbuka dalam pin 4, Buka kami di pin 4 adalah untuk mengendalikan daftar
Sisipkan penerangan imej di sini
“
Apabila kami menulis pemandu, kami hanya lakukan Tambah pemandu: Apakah yang dilakukan dengan menambah pemandu?
- Nama peranti
- Nombor peranti
- Fungsi pemacu peranti (daftar operasi untuk memacu port IO)
”
==Secara ringkasan==Jika anda ingin membuka dev
di bawahpin4
pin, prosesnya ialah: dev
下面的pin4
引脚,过程是:用户态调用open(“/de/pin4”,O_RDWR
),对于内核来说,上层调用open函数会触发一个软中断(系统调用专用,中断号是0x80,0x80代表发生了一个系统调用),系统进入内核态,并走到system_call
,可以认为这个就是此软中断的中断服务程序入口,然后通过传递过来的系统调用号来决定调用相应的系统调用服务程序(在这里是调用VFS
中的sys_open
)。sys_open
会在内核的驱动链表里面根据设备名和设备号查找到相关的驱动函数(每一个驱动函数是一个节点
Panggilan mod pengguna terbuka
"/de/pin4",O_RDWR
), untuk kernel Untuk contoh, memanggil fungsi terbuka dari lapisan atas akan mencetuskan gangguan lembut (khas untuk panggilan sistem, nombor gangguan ialah 0x80, 0x80 bermakna panggilan sistem telah berlaku), <code style="font-size: 14px;padding: 2px 4px dalam VFS
;border-radius: 4px;margin: 0 2px;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;color: #10f5d6c">sys_open ). sys_open akan mencari fungsi pemacu yang berkaitan dalam senarai pemacu kernel berdasarkan nama peranti dan nombor peranti (<code style="font-size: 14px;padding: 2px 4px; border-radius: 4px; margin: 0 2px ; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;color: #10f5d6c">Setiap fungsi pemacu ialah nod
), **==Fungsi pemacu mengandungi kod untuk mengawal port IO melalui daftar , dan kemudian boleh mengawal port IO untuk melaksanakan fungsi berkaitan ==**. 2. Penerangan terperinci setiap komponen”
“
Profil pengguna:
open,read,write,fork,pthread,socket
. Pustaka C (ia mesti disertakan dalam pustaka standard Linux): Ia adalah Clibary, yang menyediakan antara muka untuk program mengawal kerja kernel Panggilan dirangkumkan dan dilaksanakan di sini, dan dipanggil oleh yang bertulis aplikasi.
“
Keadaan kernel:
🎜”🎜🎜
Apabila pengguna ingin menggunakan peranti perkakasan tertentu, mereka memerlukan pemacu peranti mod kernel,dan kemudian memacu perkakasan untuk berfungsi, seperti yang dinyatakan dalam artikel sebelumnyawiringPi库
, menyediakan antara muka untuk pengguna mengawal peranti perkakasan , jika tiada perpustakaan wiringPi, anda perlu melaksanakan sendiri fungsi perpustakaan wiringPi, iaitu, tulis sendiri pemacu peranti. Dengan cara ini, apabila kami mendapat jenis papan lain, kami juga boleh menyelesaikan pembangunan.
Semua dalam Linux ialah fail Semua jenis fail dan peranti (seperti tetikus, papan kekunci, skrin, denyar, memori, kad rangkaian, seperti yang ditunjukkan dalam rajah di bawah) adalah semua fail, jadimemandangkan ia adalah fail, anda boleh Gunakan fungsi pengendalian fail untuk mengendalikan peranti ini .
Saya ada soalan, bagaimanakah fungsi operasi fail seperti buka dan baca tahu peranti perkakasan mana fail yang dibuka itu? ①Masukkan nama fail yang sepadan dalam fungsi buka untuk mengawal peranti yang sepadan. ②Lulus ==nombor peranti (nombor peranti utama dan nombor peranti kecil)==. Selain itu, kita juga perlu memahami lokasi pemacu ini dan cara melaksanakannya Setiap peranti perkakasan sepadan dengan pemacu yang berbeza (pemacu ini dilaksanakan oleh kita sendiri).
Pengurusan peranti Linux disepadukan rapat dengan sistem fail Pelbagai peranti disimpan dalam direktori /dev dalam bentuk fail, dipanggil ==fail peranti==*. Aplikasi boleh membuka, menutup, membaca dan menulis fail peranti ini, dan menyelesaikan operasi pada peranti sama seperti mengendalikan fail data biasa. **Untuk mengurus peranti ini, sistem nombor peranti**,*Setiap nombor peranti dibahagikan kepada ==nombor peranti utama== dan ==nombor peranti kecil==* (seperti yang ditunjukkan dalam rajah di bawah: ). *****Nombor peranti utama** digunakan untuk membezakan jenis peranti yang berbeza, manakala **Nombor peranti kecil digunakan untuk membezakan berbilang peranti daripada jenis yang sama. Untuk peranti yang biasa digunakan, Linux mempunyai nombor konvensional Contohnya, nombor peranti utama cakera keras ialah 3. ****Peranti aksara atau peranti sekat mempunyai nombor peranti utama dan nombor peranti kecil. ==Nombor peranti utama dan nombor peranti kecil secara kolektif dipanggil nombor peranti ==**.
“
Nombor peranti utama digunakan untuk mewakili pemandu tertentu.
Nombor peranti kecil digunakan untuk mewakili setiap peranti yang menggunakan pemacu ini.”
Sebagai contoh, sistem terbenam mempunyai dua penunjuk LED, dan lampu LED perlu dihidupkan atau dimatikan secara berasingan. Kemudian, anda boleh menulis pemandu peranti aksara untuk lampu LED, dan mendaftarkan nombor peranti utamanya sebagai peranti No. 5, dan nombor peranti kecilnya masing-masing sebagai 1 dan 2. Di sini, nombor peranti kedua mewakili dua lampu LED masing-masing.
==Senarai dipautkan pemandu==
“
Urus pemacu untuk semua peranti, tambah atau cari
sedang memanggil pemacu, dan ruang pengguna lapisan aplikasi menggunakan fungsi terbuka untuk mencarinyaMenambah
添加
是发生在我们编写完驱动程序,加载到内核。查找
berlaku selepas kami selesai menulis pemacu dan memuatkannya ke dalam kernel.Cari
. Turutan di mana pemandu dimasukkan ke dalam senarai dipautkan diambil oleh nombor peranti, iaitu, nombor peranti utama dan nombor peranti kecil bukan sahaja boleh membezakan jenis peranti dan jenis peranti yang berbeza , tetapi juga memuatkan pemandu ke kedudukan tertentu dalam senarai terpaut , pembangunan kod pemandu yang diperkenalkan di bawah tidak lebih daripada menambah pemandu (menambah nombor peranti, nama peranti dan fungsi pemacu peranti) dan
memanggil. pemandu.
”
Ditambah:
Prinsip kerja pemacu peranti aksara Dalam dunia Linux, semuanya adalah fail, dan semua operasi peranti perkakasan akan diabstraksikan ke dalam operasi fail pada lapisan aplikasi. Kami tahu bahawa jika lapisan aplikasi ingin mengakses peranti perkakasan, ia mesti memanggil pemacu yang sepadan dengan perkakasan. Terdapat begitu banyak pemacu dalam kernel Linux Bagaimana aplikasi boleh memanggil pemacu asas dengan tepat?
==Ilmu yang mesti diketahui:==🎜🎜struct inode
Struktur ini merekodkan semua maklumat fail, seperti jenis fail, hak akses, dsb. /dev
目录或者其他如/sys
lapisan aplikasi. struct file
struktur pada lapisan VFS untuk menerangkan fail yang dibuka. (1) Apabila fungsi terbuka membuka fail peranti, anda boleh mengetahui jenis peranti yang akan dikendalikan seterusnya (peranti aksara atau peranti blok) berdasarkan maklumat yang diterangkan oleh struktur inod struktur yang sepadan dengan fail peranti, dan struktur fail juga akan diperuntukkan.
(2) Mengikut nombor peranti yang direkodkan dalam struktur inod struct, pemacu yang sepadan boleh ditemui. Di sini kita mengambil peranti watak sebagai contoh. Dalam sistem pengendalian Linux, setiap peranti aksara mempunyai struktur cdev struktur. Struktur ini menerangkan semua maklumat peranti aksara, yang paling penting ialah antara muka fungsi pengendalian peranti aksara.
(3) Selepas mencari struktur struct cdev, kernel Linux akan merekodkan alamat pertama ruang memori di mana struktur struct cdev terletak dalam ahli i_cdev struktur inode struct, dan merekodkan alamat antara muka operasi fungsi yang direkodkan dalam struktur cdev struct Dalam ahli f_ops struktur fail struct.
(4) Apabila tugasan selesai, lapisan VFS akan mengembalikan deskriptor fail (fd) kepada aplikasi. Fd ini sepadan dengan struktur fail struct. Seterusnya, aplikasi lapisan atas boleh mencari fail struct melalui fd, dan kemudian mencari antara muka fungsi file_operation untuk mengendalikan peranti aksara dalam fail struct.
Antaranya, cdev_init dan cdev_add telah dipanggil dalam fungsi kemasukan pemacu, masing-masing melengkapkan pengikatan peranti aksara dan antara muka operasi fungsi_fail, dan mendaftarkan pemacu aksara ke kernel.
-Pemandu kernel **==Rangka kerja pemacu peranti aksara paling mudah==**:
#include #include #include #include void main() { int fd,data; fd = open("/dev/pin4",O_RDWR); if(fdprintf("open fail\n"); perror("reson:"); } else{ printf("open successful\n"); } fd=write(fd,'1',1); }
Buat nama peranti secara manual
sudo mknod +设备名字 +设备类型(c表示字符设备驱动) +主设备号+次设备号
b: buat satu blok (buffer) fail khas. c, u: cipta fail khas aksara (tidak buffer). p: buat FIFO, Untuk memadamkan nama peranti yang dibuat secara manual, hanya rm. Seperti yang ditunjukkan dalam gambar di bawah: Buka peranti melalui program lapisan atas Jika tiada pemacu, ralat akan dilaporkan semasa melaksanakan Dalam pemacu kernel, sistem lapisan atas memanggil open,wirte
函数会触发sys_call
、sys_call会调用sys_open,
和sys_write
, sys_open dan sys_write lulus nombor peranti utama. dalam senarai pemacu kernel Cari pemacu dan jalankan buka dan tulis di dalam Untuk keseluruhan proses berjalan dengan lancar, kita mesti menyediakan pemacu (fail pemacu peranti) terlebih dahulu.
Fail pemacu peranti mempunyai bingkai tetap:
module_init(pin4_drv_init);
//入口 去调用 pin4_drv_init
Fungsiint __init pin4_drv_init(void)
//Masuk masuk pemandu sebenardevno = MKDEV(major,minor);
// Cipta nombor perantiregister_chrdev(major, module_name,&pin4_fops);
//Daftarkan pemacu dan beritahu kernel untuk menambah struktur yang disediakan di atas pada senarai dipautkan pemacu kernelpin4_class=class_create(THIS_MODULE,"myfirstdemo");
// Jana peranti secara automatik di bawah dev melalui kod dan buat kelaspin4_class_dev =device_create(pin4_class,NULL,devno,NULL,module_name);
//Buat fail peranti. /dev
fail tambahan untuk lapisan atas kita dibukasudo mknod +设备名字 +设备类型(c表示字符设备驱动) +主设备号+次设备号
Kompilasi kod modul pemacu (kompilasi modul memerlukan kod sumber kernel yang dikonfigurasikan. Akhiran modul kernel yang dijana selepas penyusunan dan sambungan ialah **.ko
. Proses penyusunan akan mula-mula pergi ke direktori kod sumber kernel, baca peringkat atas Makefile fail, dan kemudian Kemudian kembali ke direktori tempat kod sumber modul berada): **
#include //file_operations声明 #include //module_init module_exit声明 #include //__init __exit 宏定义声明 #include //class devise声明 #include //copy_from_user 的头文件 #include //设备号 dev_t 类型声明 #include //ioremap iounmap的头文件 static struct class *pin4_class; static struct device *pin4_class_dev; static dev_t devno; //设备号 static int major =231; //主设备号 static int minor =0; //次设备号 static char *module_name="pin4"; //模块名 //led_open函数 static int pin4_open(struct inode *inode,struct file *file) { printk("pin4_open\n"); //内核的打印函数和printf类似 return 0; } //read函数 static int pin4_read(struct file *file,char __user *buf,size_t count,loff_t *ppos) { printk("pin4_read\n"); //内核的打印函数和printf类似 return 0; } //led_write函数 static ssize_t pin4_write(struct file *file,const char __user *buf,size_t count, loff_t *ppos) { printk("pin4_write\n"); //内核的打印函数和printf类似 return 0; } static struct file_operations pin4_fops = { .owner = THIS_MODULE, .open = pin4_open, .write = pin4_write, .read = pin4_read, }; //static限定这个结构体的作用,仅仅只在这个文件。 int __init pin4_drv_init(void) //真实的驱动入口 { int ret; devno = MKDEV(major,minor); //创建设备号 ret = register_chrdev(major, module_name,&pin4_fops); //注册驱动 告诉内核,把这个驱动加入到内核驱动的链表中 pin4_class=class_create(THIS_MODULE,"myfirstdemo");//让代码在dev下自动>生成设备 pin4_class_dev =device_create(pin4_class,NULL,devno,NULL,module_name); //创建设备文件 return 0; } void __exit pin4_drv_exit(void) { device_destroy(pin4_class,devno); class_destroy(pin4_class); unregister_chrdev(major, module_name); //卸载驱动 } module_init(pin4_drv_init); //入口,内核加载驱动的时候,这个宏会被调用,去调用pin4_drv_init这个函数 module_exit(pin4_drv_exit); MODULE_LICENSE("GPL v2");
/SYSTEM/linux-rpi-4.19.y/drivers/char
将以上代码复制到一个文件中,然后下一步要做的是就是:将上面的驱动代码编译生成模块,再修改Makefile。(你放那个文件下,就改哪个文件下的Makefile)obj-m += pin4drive.o
添加到Makefile中即可。下图:Makefile文件图
.ko
文件发送给树莓派**然后回/SYSTEM/linux-rpi-4.19.y
下使用指令:ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make modules
进行编译生成驱动模块。然后将生成的.ko
文件发送给树莓派:scp drivers/char/pin4driver.ko pi@192.168.0.104:/home/pi
编译生成驱动模块会生成以下几个文件:
.o
的文件是object文件,.ko
是kernel object,与.o的区别在于其多了一些sections,比如.modinfo
。.modinfo section
是由kernel source里的modpost工具生成的, 包括MODULE_AUTHOR, MODULE_DESCRIPTION, MODULE_LICENSE, device ID table以及模块依赖关系等等。depmod 工具根据.modinfo section生成modules.dep, modules.*map等文件,以便modprobe更方便的加载模块。“
- Semasa proses penyusunan, kami telah melalui langkah-langkah berikut:
- Mula-mula masukkan direktori di mana kernel Linux terletak dan susun fail pin4drive.o
- Menjalankan MODPOST akan menjana fail pin4drive.mod.c sementara, dan kemudian menyusun pin4drive.mod.o berdasarkan fail ini,
- Kemudian sambungkan fail pin4drive.o dan pin4drive.mod.o untuk mendapatkan fail sasaran modul pin4drive.ko,
- Akhirnya tinggalkan direktori di mana kernel Linux berada.
”
Kompil silang pin4test.c (kod panggilan lapisan atas) dan hantar ke Raspberry Pi Anda boleh melihat bahawa terdapat dua fail yang dihantar di bawah direktori pi, seperti yang ditunjukkan dalam rajah di bawah: .ko文件
和pin4test
.
sudo insmod pin4drive.ko
加载内核驱动(相当于通过insmod调用了module_init这个宏,然后将整个结构体加载到驱动链表中) 加载完成后就可以在dev
下面看到名字为pin4
lsmod
sudo chmod 666 /dev/pin4
pin4test
Di permukaan, tiada output maklumat. Malah, terdapat maklumat pencetakan dalam kernel, tetapi ia tidak dapat dilihat oleh lapisan atas. Jika anda ingin melihat maklumat yang dicetak oleh kernel , anda boleh menggunakan arahan: dmesg |grep pin4
. Seperti yang ditunjukkan dalam gambar di bawah: ia bermakna panggilan pemandu berjayapin4test
表面上看没有任何信息输出,其实内核里面有打印信息只是上层看不到如果想要查看内核打印的信息可以使用指令:dmesg |grep pin4
Selepas memasang pemacu, anda boleh menggunakan arahan:
Mengapa modul pemacu yang dijana perlu dijana pada mesin maya? Tidakkah Raspberry Pi berfungsi?
Menjana modul pemacu memerlukan persekitaran kompilasi (kod sumber dan kompilasi Linux, anda perlu memuat turun kod sumber kernel Linux yang sama dengan versi sistem Ia juga boleh disusun pada Raspberry Pi, tetapi mengkompil pada Raspberry Pi akan menjadi sangat tidak cekap dan memerlukan Sangat lama . Artikel ini membincangkan tentang kompilasi tempatan pemacu Raspberry Pi.
Atas ialah kandungan terperinci Linux Intermediate - "Pemandu" Pengetahuan peringkat rendah yang mesti dipelajari untuk mengawal perkakasan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!