1. 程式人生 > >裝置驅動歸納總結(八):1.匯流排、裝置和驅動 —— 匯流排的註冊

裝置驅動歸納總結(八):1.匯流排、裝置和驅動 —— 匯流排的註冊

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

這幾天一直在看裝置模型,核心的程式碼看得我越來越沮喪,特別是kbojectksetktype之間的關係。但是,裝置模型的歸納我打算先跳過這幾個重要結構體,先介紹匯流排、裝置和驅動——裝置管理的相關內容。先介紹如何使用,有機會介紹大概的原理。

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

一、sysfs檔案系統

裝置模型是2.6核心新引入的特徵。裝置模型提供了一個獨立的機制專門來表示裝置,並描述其在系統中的拓撲結構。

2.4核心中,裝置的資訊放在/proc中。

而在2.6核心,核心把裝置相關的資訊歸類在新增加sysfs檔案系統,並將它掛載到/sys目錄中,把裝置資訊歸類的同時,讓使用者可以通過使用者空間訪問。

接下來簡單介紹一些sys中的目錄:

block:用於管理塊裝置,系統中的每一個塊裝置會在該目錄下對應一個子目錄。

bus:用於管理匯流排,沒註冊一條匯流排,在該目錄下有一個對應的子目錄。

其中,每個匯流排子目錄下會有兩個子目錄:

devicesdrivers

devices包含裡系統中所有屬於該匯流排的的裝置。

drivers包含裡系統中所有屬於該匯流排的的驅動。

class:將系統中的裝置按功能分類。

devices:該目錄提供了系統中裝置拓撲結構圖。

dev:該目錄已註冊的裝置節點的檢視。

kernel:核心中的相關引數。

module:核心中的模組資訊。

fireware:核心中的韌體資訊。

Fs:描述核心中的檔案系統。

上面的目錄,接下來的章節會常常提起busdevice

再說說這些目錄,來個簡單的命令:

[email protected]

:/sys# ll class/net/eth0

lrwxrwxrwx 1 root root 0 2011-01-31 10:11 class/net/eth0 -> ../../devices/pci0000:00/0000:00:1c.5/0000:86:00.0/net/eth0/

上面的命令也可以看到class/net/eth0的路徑其實就是devices目錄中一個網絡卡裝置的軟連線

貼個書上的圖:

由上面兩個例子看到,sys中的其他目錄都是將devvice目錄下的資料加以轉換加工而得。上面的圖中,將use裝置歸類到bus總線上,又把它歸類到class。正是在sys中有很多這樣的結構,核心就有一個完整而且複雜的拓撲結構圖。

而維護這些關係的結構體就包括kobjectksetktypesubsystem等資料結構,不過這裡就先不介紹。

通過裝置模型,核心就能實現多種不同的任務,如:

1、電源管理和系統關機。

2、與使用者空間通訊。這個就比較容易理解,sys目錄向用戶展示了裝置模型的結構圖。

3、熱插拔裝置。大概意思就是,當裝置插入後,核心會根據插入的裝置安裝驅動,裝置拔出後,核心又會自動解除安裝驅動。

4、裝置型別。將裝置歸類。

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

在接下來的內容會簡單介紹匯流排、裝置和驅動程式的概念和函式呼叫,以下的函式我將模擬建立一條ubs匯流排,一個usb裝置和一個usb驅動。

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

二、匯流排

匯流排是處理器和裝置之間的通道,在裝置模型中,所有的裝置都通過匯流排相連,以匯流排來管理裝置和驅動函式。匯流排有bus_type結構表示。

/*linux/device.h*/

51 struct bus_type {

52 const char *name;

53 struct bus_attribute *bus_attrs;

54 struct device_attribute *dev_attrs;

55 struct driver_attribute *drv_attrs;

56

57 int (*match)(struct device *dev, struct device_driver *drv);

58 int (*uevent)(struct device *dev, struct kobj_uevent_env *env);

59 int (*probe)(struct device *dev);

60 int (*remove)(struct device *dev);

61 void (*shutdown)(struct device *dev);

62

63 int (*suspend)(struct device *dev, pm_message_t state);

64 int (*suspend_late)(struct device *dev, pm_message_t state);

65 int (*resume_early)(struct device *dev);

66 int (*resume)(struct device *dev);

67

68 struct dev_pm_ops *pm;

69

70 struct bus_type_private *p;

71 };

紅色部分是以後將會介紹的成員,其中name是匯流排的名字, bus_attrs是匯流排的屬性,那些函式指標的操作匯流排的方法,在這一章節先不講匯流排的方法。

匯流排的註冊和刪除:

匯流排的註冊有兩個步驟:

1、定義一個bus_type結構體,並設定好需要設定的結構體成員。

2、呼叫函式bus_register註冊匯流排。函式原型如下:

/*drivers/base/bus.c*/

865 int bus_register(struct bus_type *bus)

該呼叫有可能失敗,所以必須檢查它的返回值,如果註冊成功,會在/sys/bus下看到指定名字的匯流排。

匯流排刪除時呼叫:

/*drivers/base/bus.c*/

946 void bus_unregister(struct bus_type *bus)

接下來貼個函式:

/*8th_devModule_1/1st/bus.c*/

1 #include

2 #include

3

4 #include

5

6 struct bus_type usb_bus = {

7 .name = "usb", //定義匯流排的名字為usb,註冊成功後將在/sys/bus目錄下看到

8 }; //目錄usb,如果你的系統已經有usb匯流排,那你就要換個名字。

9

10 static int __init usb_bus_init(void)

11 {

12 int ret;

13 /*匯流排註冊,必須檢測返回值*/

14 ret = bus_register(&usb_bus);

15 if(ret){

16 printk("bus register failed!\n");

17 return ret;

18 }

19

20 printk("usb bus init\n");

21 return 0;

22 }

23

24 static void __exit usb_bus_exit(void)

25 {

26 bus_unregister(&usb_bus);

27 printk("usb bus bye!\n");

28 }

29

30 module_init(usb_bus_init);

31 module_exit(usb_bus_exit);

32

33 MODULE_LICENSE("GPL");

上面的函式可以看到,我僅僅定義了匯流排的名字為usb,其他的都沒有做。看看效果:

[root: 1st]# insmod bus.ko

usb bus init

[root: 1st]# ls /sys/bus/usb/ //sys/bus目錄下多了一個usb的目錄,但是裡面的東西都是空的,

devices drivers_autoprobe uevent //因為我僅僅設定了匯流排的名字

drivers drivers_probe

匯流排屬性新增和刪除:

個人理解,設定匯流排的屬性後,會在對應的匯流排目錄下增加了一個新的檔案,通過對該檔案的讀寫訪問,觸發相應的函式操作,從而實現/sys/的檔案介面與核心裝置模型的資料互動

/*linux/sysfs.h*/

28 struct attribute {

29 const char *name; //設定該檔案的名字

30 struct module *owner; //設定該檔案的屬主

31 mode_t mode; //設定該檔案的檔案操作許可權

32 };

/*linux/device.h*/

38 struct bus_attribute {

39 struct attribute attr;

40 ssize_t (*show)(struct bus_type *bus, char *buf);

41 ssize_t (*store)(struct bus_type *bus, const char *buf, size_t count);

42 };

bus_attribute中有兩個函式指標,showstore

當訪問匯流排目錄中的name檔案時,就會觸發show函式,一般會將指定的資訊存放到陣列buf,並傳到使用者空間顯示。

當修改匯流排目錄中的name檔案是,就會觸發stroe函式,一般會將從使用者空間傳來的buf指標存放的count個位元組內容存放到核心中。

由此可以看到,通過這樣的檔案,就能實現sys目錄下的檔案與核心裝置模型之間的資料互動。

設定匯流排屬性有兩個步驟:

1、建立並初始化bus_attribute結構,使用巨集BUS_ATTR

BUS_ATTR(_name, _mode, _show, _store)

該巨集會定義一個名叫bus_attr__name(紅色部分是固定的)的bus_attibute的結構,並且成員name設定為_name,檔案許可權mode設定為_mode,兩個函式呼叫分別人showstore

2、將bus_attibute新增到指定的總線上,使用以下呼叫:

/*/drivers/base/bus.c*/

123 int bus_create_file(struct bus_type *bus, struct bus_attribute *attr)

該函式失敗時返回錯誤號。

一旦呼叫該函式,會就在指定bus匯流排的目錄下新建一個名叫_name的檔案,許可權為_mode,當訪問和修改該檔案是會分別呼叫showstore函式呼叫。

如果不需要該屬性時,使用以下函式刪除:

/*/drivers/base/bus.c*/

135 void bus_remove_file(struct bus_type *bus, struct bus_attribute *attr)

說了這麼多,馬上來個程式:

/*8th_devModule_1/2nd/bus.c*/

1 #include

2 #include

3

4 #include

5

6 #define VER_SIZE 100

7

8 struct bus_type usb_bus = {

9 .name = "usb",

10 };

11

12 char Version[VER_SIZE] = "xiaobai V1.0";

13

14 static ssize_t show_bus_version(struct bus_type *bus, char *buf)

15 {

16 return snprintf(buf, VER_SIZE, "%s\n", Version);

17 }

18 static ssize_t store_bus_version(struct bus_type *bus, const char *buf, size_t count)

19 {

20 return snprintf(Version, VER_SIZE, "%s", buf);

21 }

22 /*該巨集會定義一個名叫bus_attr_versionbus_attribute的結構,並且成員name設定為

23 * version,檔案許可權mode設定為S_IRUGO|S_IWUGO,並設定show函式為

24 * show_bus_versionstror 函式為stroe_bus_version*/

25 static BUS_ATTR(version, S_IRUGO|S_IWUGO, show_bus_version, store_bus_version);

26

27 static int __init usb_bus_init(void)

28 {

29 int ret;

30

31 /*匯流排註冊*/

32 ret = bus_register(&usb_bus);

33 if(ret){

34 printk("bus register failed!\n");

35 goto err1;

36 }

37 /*為匯流排新增屬性,呼叫成功後在/sys/bus/usb目錄下有一個version的檔案,許可權為

38 * S_IRUGO|S_IWUGO,檢視該檔案時會呼叫函式show_bus_version,修改時呼叫store*/

39 ret = bus_create_file(&usb_bus, &bus_attr_version);

40 if(ret){

41 printk("bus creat file failed!\n");

42 goto err2;

43 }

44 printk("usb bus init\n");

45 return 0;

46

47 err2:

相關推薦

裝置驅動歸納總結1.匯流排裝置驅動 —— 匯流排註冊

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 這幾天一直在看裝置模型,核心的程式碼看得我越來越沮喪,特別是kboject、kset和ktype之間的關係。但是,裝置

linux裝置驅動歸納總結1.platform匯流排裝置驅動

linux裝置驅動歸納總結(九):1.platform匯流排的裝置和驅動 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 這一節可

linux裝置驅動歸納總結1.platform裝置驅動

http://blog.chinaunix.net/uid-25014876-id-111745.html 這一節可以理解是第八章的延伸,從這節開始介紹platform裝置驅動。 一、什麼是paltform匯流排 一個現實的linux裝置和驅

linux裝置驅動歸納總結2.操作硬體——IO記憶體

<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSi

linux裝置驅動歸納總結3.中斷下半部之tasklet

linux裝置驅動歸納總結(六):3.中斷的上半部和下半部——tasklet xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 一、什麼是下半部 中斷是一個很霸道的東西,處理

java基礎學習總結Java中的反射

Native      JDK開放給使用者的原始碼中隨處可見Native方法,被Native關鍵字宣告的方法說明該方法不是以Java語言實現的,而是以本地語言實現的,Java可以直接拿來用。這裡有一個概念,就是本地語言,本地語言這四個字,個人理解應該就是可以和作業系

Maven學習總結Myecplise中配置maven

第一步:下載maven安裝包,配置環境變數M2_HOME;變數值為maven的解壓目錄。 第二步:在eclipse4.0之前的版本需要安裝maven外掛,方法即:將maven外掛包複製到eclipse安裝目錄的dropins資料夾下,安裝之後版本的eclipse和myeclipse,無需安裝外掛。本人是用的

ElasticSearch學習總結外掛的開發

本文主要總結Elasticsearch 自定義 REST 介面的外掛開發流程。 1. 外掛介紹 本外掛邏輯比較簡單,主要用來返回包含指定字首的節點列表。 2. 程式碼說明 外掛主要包括兩部分的內容,一部分用來對外掛的註冊,另一部分負責對業務邏輯的處理 外掛註冊部分:

Java執行緒總結併發包------讀寫鎖ReadWriteLock的簡單例子詳細理解

初次接觸ReadWriteLock類時也在網上查了很多資料,很容易瞭解到ReadWriteLock是讀寫鎖,並且讀寫鎖的機制有以下三個特點:  讀鎖---讀鎖    (不互斥)  讀鎖---寫鎖     (互斥)  寫鎖---寫鎖     (互斥)什麼意思呢?網上很多資料,

flume常見sourcechannelsink總結

一、核心關注點 因為flume版本不同,source、channel和sink的介面都是不一樣的,所以需要使用對應版本的介面。 本文以flume1.6.0為例,參考http://archive.cloudera.com/cdh5/cdh/5/flume-ng-1.6.0-c

C++ STL開發溫習與總結 1.C++程式設計技術

 C++ STL開發溫習與總結(一):1.C++程式設計技術       使用了多年C++,沒有系統的溫習總結過,所以準備溫習《C++STL程式設計師開發指南》,本系列篇章將會是溫習總結該書本概念和技術點。 1概論 l  C++語言是基於C語言的語法基礎上融入了其他語

Scala基礎教程模式匹配正則表示式

匹配使用case 類: case classes是用於模式匹配與case 表示式指定類。這些都是標準類具有特殊修飾:case。下面是一個簡單的模式使用case class匹配示例: object Test {    def main(args: Array[String])

用Java實現JVM支援介面物件

1. 概述我的 JVM 已經能夠執行HelloWorld了,並且有了基本的 JVM 骨架,包括執行時資料結構的定義(棧、棧幀、運算元棧等),執行時的邏輯控制等。但它還沒有類和物件的概念,比如無法執行下面這更復雜的HelloWorld:public interface SpeakerInterface {

Visual Studio 2008 可擴充套件性開發操作SolutionProjectProjectItem

string classLibProjTemplatePath =     sln.GetProjectTemplate("ClassLibrary.zip", "CSharp");string domainProjName = slnName +"."+"Domain";sln.AddFromTemplat

Python3+OpenCV學習筆記影象載入顯示儲存

img = cv2.imread('Rachel.jpg')載入影象後,當然需要顯示出來,我們才能看到,所以,接下來用到第二個函式cv2.imshow(windowname, filename)“windowname”輸入顯示視窗的名稱,引數型別str,需要開啟多個視窗時,只需要“windowname”不同

軟件架構設計學習總結14大型網站技術架構網站的安全架構

根據 知情 提交 pac 請求參數 用途 text 避免 信息加密 從互聯網誕生起,安全威脅就一直伴隨著網站的發展,各種Web攻擊和信息泄露也從未停止。常見的攻擊手段有XSS攻擊、SQL註入、CSRF、Session劫持等。 1、XSS攻擊 XSS攻擊即跨站點腳本攻擊(C

設計模式學習總結策略模式(Strategy)

isp 筆記本 override div ont 角色 write stat 通過   策略模式,主要是針對不同的情況采用不同的處理方式。如商場的打折季,不同種類的商品的打折幅度不一,所以針對不同的商品我們就要采用不同的計算方式即策略來進行處理。   一、示例展示:   以

Hibernate基於外鍵映射的1-1關聯關系

hbm 初始化 inno oot type nat create getc source 背景: 一個部門只有一個一把手,這在程序開發中就會設計數據映射應該設置為一對一關聯。 在hibernate代碼開發中,實現這個業務有兩種方案: 1)基於外鍵映射的1-1關

x264代碼剖析encode()函數之x264_encoder_close()函數

name sequence img float 通過 例如 b16 trac 不為 x264代碼剖析(八):encode()函數之x264_encoder_close()函數 encode()函數是x264的主幹函數。主要包含x264_enc

Java-NIODatagramChannel

reg lin mov div 數據 selector sca gist put Java NIO中的DatagramChannel是一個能收發UDP包的通道。操作步驟:  1)打開 DatagramChannel  2)接收/發送數據 同樣它也支持NIO的非阻塞模式操作