轉自:http://blog.csdn.net/dreaming_my_dreams/article/details/8272586
應用層和驅動的銜接,一直是一個老大難問題,若弄不清楚,總覺得驅動寫起來似是而非的。下面就說說我對他們的理解,還有就是如何實現一個驅動支持多個上設備的問題。最主要涉及兩個機制:inode和file
1. 在驅動中
- 我們先找到一個設備號devno,可以動態申請,也可以靜態設定,假設靜態設定為major,minor,通過宏MKDEV(major,minor)來生成devno
- 構建對設備的操作函數集file_opreation結構體,里面包含了的設備的操作:open、read、write、release、ioctl等
- 構建cdev結構體,里面填充兩個主要成員dev(設備號)、file_operation(對設備的操作)
- 把cdev添加到cdev鏈表中:cdev_init、cdev_add
舉個例子,tty驅動:
-->__init imx_serial_init //imx.c
-->uart_register_driver //serial_core.c
-->tty_regiser_driver //tty_io.c
-->MKDEV(driver->major, driver->minor_start) //tty_io.c
-->tty_cdev_add //tty_io.c
-->cdev_init(tty_fops) //tty_io.c, struct file_operations tty_fops={.open;.read;.write}
-->cdev_add //tty_io.c
就這樣,一步步將file_operation的函數集加入到cdev->ops中,而User層則根據設備號找到cdev鏈表中對應的設備屬性,從而找到函數集。
2. 應用程序中
fd=open("/dev/hello",O_RDWR)來打開設備文件,此設備對應有一個設備號,這是我們識別驅動和設備的橋梁。
設備號、設備文件、設備節點概念:設備號由主設備號和從設備號組成,設備號是16bit, 高8bit為主設備號,低8bit為從設備號。/dev下每個設備都有對應的設備文件,即設備節點。
打開 /dev/hello時,根據設備號,在cdev鏈表中找到cdev這個結構體,cdev里面包含了file_operation結構體,有設備的各種操作,打開時就調用里面的.open 函數。在這里要完成幾件事:
- inode節點 每一個文件都對應有一個inode節點,inode結構體里.i_fop由cdev的file_operation填充,i_dev由cdev的設備號填充
- file結構體中的file_operation也同樣由cdev中對應項填充,還有一項fd,對應於打開文件的文件描述符,fd和file一一對應,文件每打開一次,就有一個file結構。所以file里面的.private就很重要,下面會說到。
還有一個問題,那就是多個相同的設備,會公用同一個驅動(一個驅動文件1個主設備號如uart),所以要把每一個設備的私有數據封裝起來,構成一個私有數據結構體。對設備的每一次讀寫,都通過操作設備的私有數據結構體中的資源來完成。也就是說,驅動在加載的時候,會申請多個設備私有資源結構體,每個結構體中包含了設備的所有私有資源,雖然公用一個驅動,可是通過設備號找到此設備號對應設備的私有資源,說的有點拗口。這可以通過file結構體的.private來指向。
例如封裝私有數據的結構體為:
struct hello_device{
char buf[128]; //設備的私有資源,譬如buf
struct cdev cdev;//設備結構體,里面有devno和file_operation
……
};
前面應經提到inode中的i_cdev會指向cdev結構,所以可以由Container宏來得到hello_device的地址。
所以,在驅動的open函數中有兩個參數,inode和file
int open(structc inode *inode,struct file *file){
struct hello_device *p =container(inode->i_cdev,hello_struct,cdev)
file->private=p;
}
這樣file中就包含了設備的私有數據。
驅動read函數中:
ssize_t read(fd,char __user *buf,count)
fd和file一一對應,每打開一次設備,雖然有不同的fd,但他們的file.private是一樣的。
每打開一個設備文件,把私有數據和file綁定,這樣后面的read/write操作,由於fd和file一一對應,這樣,read/write也就通過fd句柄就可以訪問到file->private數據了。
前面主要說了一個驅動如何可以支持多個設備的問題,以及應用層和驅動之間的聯系。還有一個問題就是,如何處理過多個進程訪問同一個設備的問題。
-----------------------------------------------------------------------------------------------------------------------------------------------------------
轉自:http://blog.chinaunix.net/uid-20543672-id-3203690.html
最近在看《深入Linux設備驅動程序機制》,這本書條理清晰,我從中獲益良多。以前在學習內核驅動的時候就是知道怎么用,對於內部的原理了解的不是這么深入。且當時的能力有限,想了解深入也不容易。這次正好趁復習驅動原理的機會,把這本書認真學習以下。