[內核]Linux UserSpace和Kernel之間如何聯系


轉自:http://blog.csdn.net/dreaming_my_dreams/article/details/8272586

應用層和驅動的銜接,一直是一個老大難問題,若弄不清楚,總覺得驅動寫起來似是而非的。下面就說說我對他們的理解,還有就是如何實現一個驅動支持多個上設備的問題。最主要涉及兩個機制:inode和file

1. 在驅動中

  1. 我們先找到一個設備號devno,可以動態申請,也可以靜態設定,假設靜態設定為major,minor,通過宏MKDEV(major,minor)來生成devno
  2. 構建對設備的操作函數集file_opreation結構體,里面包含了的設備的操作:open、read、write、release、ioctl等
  3. 構建cdev結構體,里面填充兩個主要成員dev(設備號)、file_operation(對設備的操作)
  4. 把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 函數。在這里要完成幾件事:

  1. inode節點 每一個文件都對應有一個inode節點,inode結構體里.i_fop由cdev的file_operation填充,i_dev由cdev的設備號填充
  2. 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設備驅動程序機制》,這本書條理清晰,我從中獲益良多。以前在學習內核驅動的時候就是知道怎么用,對於內部的原理了解的不是這么深入。且當時的能力有限,想了解深入也不容易。這次正好趁復習驅動原理的機會,把這本書認真學習以下。

 
    在第二章講解字符設備的時候,個人覺得比較有收獲的主要是兩個方面的知識:
1、字符設備號的管理原理(char_device_struct)
2、字符設備驅動的file_operation中的函數如何與file結構體中的相應結構對應上,並被應用程序調用。
 
    對於以上兩個主要的知識點,我覺得書上的條理已經很清楚的,很容易看懂,我在這里復述就多余了。我把學到的兩個知識點用圖的方式總結出來,供大家參考。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1、字符設備號的管理原理

    重點在於內核在管理時 所依賴數據結構char_device_struct以及全局的 散列表chrdevs。
    還有就是要知道內核對於設備號的注冊與注銷和驅動功能的實現是沒有必然的聯系的。設備號的管理是一個獨立的機制,以避免驅動在使用設備號的時候發生沖突,導致驅動中的file_operation對應錯誤,進而出現應用層操作錯誤的設備。因為 應用層對設備的操作就是通過設備號對應到具體的file_operation的
 
 
 

2、字符設備驅動的file_operation中的函數如何與file結構體中的相應結構對應上,並被應用程序調用

   這部分的內容主要是要熟悉open函數的調用流程,驅動中的file_operation結構體就是在 open函數中通過設備號與進程相關的file結構體中相應函數進行對應的。在完成了open操作之后,其他的文件操作就可以直接調用驅動file_operation中的函數了。
   內核對於char_device_struct結構體的管理方式和設備號的cdev_map是類似的,都是通過主設備號作為哈希表的key來索引。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM