Linux下驅動 分層 分離機制學習筆記

2021-07-09 08:56:54 字數 4851 閱讀 5489

一、分層、分離的概念

分層即把硬體相關和相對穩定的東西給抽出來,並向上提供統一的介面,每一層專注於自己的事情,比如輸入子系統。後續文章中會繼續介紹相關例子;

分離即把硬體相關和相對穩定的東西給分離開來,實際上即是bus-dev-drv模型(平台匯流排、平台裝置、平台驅動),本文章中的led驅動即使用了此模型。

二、bus-dev-drv模型

在硬體相關部分(即硬體操作的部分,其實在drv中也會有操作硬體,只是基本上不用改動,比較穩定。要改硬體,一般改dev部分**即可。),入口函式中會呼叫platform_device_register→platform_device_add→device_add,device_add函式的作用如下:

(1)把device(結構體)放入bus(結構體)的dev鍊錶中去。即註冊。

(2)從bus(結構體)的drv(結構體)鍊錶中取出每個drv,用bus的match函式判斷drv能否支援此dev。

(3)如果支援(實際上是判斷結構的.name成員是否一樣),呼叫drv(結構體)的probe函式。

在driver相關部分,會向上註冊乙個結構體,實際上就是呼叫platform_driver_register函式→driver_register函式把driver結構體放到bus 裡(結構體)的driver煉表裡:

(1)把driver(結構體)放入bus(結構體)的drv鍊錶中去。 即註冊。

(2)從bus(結構體)的dev(結構體)鍊錶中取出每個dev,跟此drv一一比較(用bus的match函式去比較)。

(3)如果支援,呼叫drv(結構體)的probe函式。

總的來說,上述只不過是左右建立一種聯絡的機制,在probe裡面做什麼完全由自己決定,比如列印一句話,註冊乙個字元裝置,或者註冊乙個input_dev結構體。如果要修改硬體,只需要修改硬體相關的**即可,右邊比較穩定的**可以不動,這樣大家就有一種約定,其實不管是device還是driver(它們只是乙個結構體而已)。

三、bus-dev-drv模型

具體例項

以乙個led驅動的例子說明分層分離的概念,原始碼分為led_dev.c,led_drv.c,led_test.c。led_dev.c為硬體相關,led_drv.c為右邊較穩定的部分**,led_test.c為應用程式測試**。基本功能是點亮或關閉led燈。

其實這個程式完全可以用簡單的字元型驅動程式框架實現,這裡只是為了理解平台匯流排、裝置、驅動模型,而用此框架實現的驅動。

具體**如下:

led_dev.c :

/* 分配/設定/註冊乙個platform_device */

#include #include #include #include #include #include #include #include #include #include #include /* "~~~~~~~~~~~tiny4412支援的linux3.5中不需要用資源的方式~~~~~~~~~~~"

static struct resource led_resource = ,

//哪根引腳,如果要換乙個led亮,只需要修改下面的數字即可

[1] =

};*/

static void led_release(struct device * dev)

static struct platform_device led_dev = ,

};static int led_dev_init(void)

static void led_dev_exit(void)

module_init(led_dev_init);

module_exit(led_dev_exit);

module_license("gpl");

led_drv.c :

/* 分配/設定/註冊乙個platform_driver */

#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define device_name "bus_dev_drv_leds"

#define led_num array_size(led_gpios)

static int led_gpios = ;

/*static int major;

static struct class *cls;

static volatile unsigned long *gpio_con;

static volatile unsigned long *gpio_dat;

static int pin;

*/static int led_open(struct inode *inode, struct file *file)

static ssize_t led_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)

if (val == 1)

s3c_gpio_cfgpin(led_gpios[i], s3c_gpio_output);

gpio_set_value(led_gpios[i], 1); }

/* 註冊字元裝置驅動程式 */

printk("led_drv: led_probe, found led\n");

misc_register(&tiny4412_led_dev);

/* major = register_chrdev(0, "myled", &led_fops);

cls = class_create(this_module, "myled");

class_device_create(cls, null, mkdev(major, 0), null, "led"); //裝置檔案dev/led

*/ return 0;

}static int led_remove(struct platform_device *pdev)

misc_deregister(&tiny4412_led_dev);

/* class_device_destroy(cls, mkdev(major, 0));

class_destroy(cls);

unregister_chrdev(major, "myled");

iounmap(gpio_con);

*/ return 0;

}struct platform_driver led_drv =

};static int led_drv_init(void)

static void led_drv_exit(void)

module_init(led_drv_init);

module_exit(led_drv_exit);

module_license("gpl");

led_test.c :

#include #include #include #include /* led_test on

* led_test off

*/int main(int argc, char **argv)

if (argc != 2)

if (strcmp(argv[1], "on") == 0)

else

write(fd, &val, 4);

return 0;

}

makefile:

kern_dir = /home/samba/linuxkernel_ext4fs_src/linux-3.5-2015-8

all:

make -c $(kern_dir) m=`pwd` modules

clean:

make -c $(kern_dir) m=`pwd` modules clean

rm -rf modules.order

obj-m += led_drv.o

obj-m += led_dev.o

如果是先裝載led_dev,會把dev加入bus的裝置鍊錶中去,然後找對應的drv,此時找不到沒關係,等裝載了led_drv後,會把drv加入到bus的driver鍊錶中去,然後會在dev鍊錶中找一遍有沒有匹配的dev(這樣就相當於再找了一遍,只是找的是dev而已)

,如果找到,也將呼叫drv的probe函式。所以,不管是在dev鍊錶中找裝置還是在drv鍊錶中找驅動,只要找到了,都會呼叫drv中的probe函式,這樣裝置和驅動可以不同時載入,也可不分順序載入,

通過試驗也表明,不管先裝載led_drv.ko還是先裝載led_dev.ko,都是等兩個都裝載了後才會匹配並呼叫drv的probe函式。

所以說,不管先載入led_dev.ko還是led_drv.ko,只要匹配了,就會呼叫drv結構的probe函式成員。不管先解除安裝led_dev還是led_drv,凡是第乙個解除安裝後,就會呼叫drv結構的led_remove函式成員。

驅動分層 分離,匯流排驅動裝置模型

先介紹一下驅動的分層 分離。如下圖 input.c為應用程式提供了介面,是核心層,而在核心層下面的那一層由兩方面組成,乙個是純軟體的,裡面是很穩定的 還有乙個是與硬體相關的 一般只需要通過修改與硬體相關的 而達到我們的目的。再介紹乙個概念,匯流排 驅動 裝置模型。如下圖 bus driver dev...

《驅動設計的思想 物件導向 分層 分離》

1.物件導向 字元裝置驅動程式抽象出乙個 file operations 結構體 我們寫的程式針對硬體部分抽象出 led operations 結構體。在linux核心中,所謂的物件導向可以理解為用結構體來表示某個物件。2.分層 上下分層,比如我們前面寫的 led 驅動程式就分為 2 層 上層實現硬...

6410之驅動程式的分層分離,匯流排裝置驅動模型

什麼是分離分層的概念?如前面的input子系統所述,分離分層概念可以如下圖所示 input.c和buttons.c,evdev.c形成分層的概念,buttons.c和evdev.c形成分離的概念,一邊是硬體相關的 由編寫驅動的人員編寫,一邊是純軟體是由linux核心所提供的。匯流排驅動裝置模型 該模...