最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Linux之platform平臺設(shè)備驅(qū)動詳解

 更新時間:2025年07月22日 15:08:22   作者:大肥周  
Linux設(shè)備驅(qū)動模型中,Platform總線作為虛擬總線統(tǒng)一管理無物理總線依賴的嵌入式設(shè)備,通過platform_driver和platform_device注冊,結(jié)合設(shè)備樹的of_match_table匹配機制,實現(xiàn)驅(qū)動與設(shè)備的自動綁定,確保無論注冊順序如何均能正確觸發(fā)probe函數(shù)

在 Linux 設(shè)備驅(qū)動模型中,總線(Bus)是連接處理器與設(shè)備的橋梁,而 Platform 總線是一種虛擬總線,專門用于管理那些不依賴于物理總線(如 I2C、PCI、USB 等)的嵌入式設(shè)備(如 SoC 內(nèi)部的硬件外設(shè))。

所以platform 總線的主要作用就是統(tǒng)一設(shè)備模型,將未掛載到物理總線的設(shè)備納入統(tǒng)一的設(shè)備驅(qū)動框架。

通過 platform_bus_type 虛擬一條總線,使得這些設(shè)備可以像物理總線設(shè)備一樣被管理。

platform驅(qū)動注冊

結(jié)構(gòu)體是struct platform_driver,主要包含probe、remove等接口。

struct platform_driver {
	int (*probe)(struct platform_device *);

	/*
	 * Traditionally the remove callback returned an int which however is
	 * ignored by the driver core. This led to wrong expectations by driver
	 * authors who thought returning an error code was a valid error
	 * handling strategy. To convert to a callback returning void, new
	 * drivers should implement .remove_new() until the conversion it done
	 * that eventually makes .remove() return void.
	 */
	int (*remove)(struct platform_device *);
	void (*remove_new)(struct platform_device *);

	void (*shutdown)(struct platform_device *);
	int (*suspend)(struct platform_device *, pm_message_t state);
	int (*resume)(struct platform_device *);
	struct device_driver driver;
	const struct platform_device_id *id_table;
	bool prevent_deferred_probe;
	/*
	 * For most device drivers, no need to care about this flag as long as
	 * all DMAs are handled through the kernel DMA API. For some special
	 * ones, for example VFIO drivers, they know how to manage the DMA
	 * themselves and set this flag so that the IOMMU layer will allow them
	 * to setup and manage their own I/O address space.
	 */
	bool driver_managed_dma;
};

驅(qū)動注冊接口是platform_driver_register,主要是把bus配成platform_bus_type后調(diào)用driver_register注冊。

代碼示例:

int zsl_drv_probe(struct platform_device *dev)
{
	struct property *pp = NULL;

	printk(KERN_INFO "%s: \n",__func__);

	dump_stack();  // 打印堆棧

    return 0;
}

int zsl_drv_remove(struct platform_device *dev)
{
	printk(KERN_INFO "%s: \n",__func__);
    return 0;
}

struct platform_driver zsl_drv =
{
    .driver =
    {
        .name = "zsltest",			
    },
     
    .probe = zsl_drv_probe,
    .remove = zsl_drv_remove,
};

再使用platform_driver_register(&zsl_drv)注冊這個驅(qū)動。

platform設(shè)備注冊

結(jié)構(gòu)體是struct platform_device,主要包含probe、remove等接口。

struct platform_device {
	const char	*name;
	int		id;
	bool		id_auto;
	struct device	dev;
	u64		platform_dma_mask;
	struct device_dma_parameters dma_parms;
	u32		num_resources;
	struct resource	*resource;

	const struct platform_device_id	*id_entry;
	/*
	 * Driver name to force a match.  Do not set directly, because core
	 * frees it.  Use driver_set_override() to set or clear it.
	 */
	const char *driver_override;

	/* MFD cell pointer */
	struct mfd_cell *mfd_cell;

	/* arch specific additions */
	struct pdev_archdata	archdata;
};

注冊接口是platform_device_register,主要是把設(shè)備屬性填充后,后調(diào)用device_add注冊。

代碼示例:

struct platform_device zsl_dev =
{
    .name = "zsltest",
    .dev =
    {
        .release = zsl_dev_release,
    },
};

再使用platform_device_register(&zsl_dev)注冊這個設(shè)備,其中zsl_dev里的name和zsl_drv的name保持一樣,才能讓platform device和platform driver匹配上,從而調(diào)用zsl_drv.probe。

跟platform驅(qū)動注冊配套使用后,運行打印如下,可以看到zsl_drv.probe會被調(diào)用到。

運行結(jié)果:

  • 先注冊dev,再注冊drv

  • 先注冊drv,再注冊dev

設(shè)備樹

支持設(shè)備的內(nèi)核里,更推薦使用設(shè)備樹的方式,而不是platform設(shè)備注冊的方式。

去掉zsl_dev設(shè)備的注冊代碼,在zsl_drv變量里增加.of_match_table = zsl_of_match,并且zsl_of_match表里增加.compatible = "rockchip,zslzsl",然后在設(shè)備樹里增加以下代碼。

保持兩邊的compatible一致,并且status是okay的。

這樣就會調(diào)用zsl_drv.probe,并且可以拿到設(shè)備樹里的屬性內(nèi)容。

       zsl: zsl {
              compatible = "rockchip,zslzsl";
              status = "okay";
              testdata = "test";
       };

如下修改zsl_drv_probe接口,增加拿testdata屬性的代碼

int zsl_drv_probe(struct platform_device *dev)
{
       struct property *pp = NULL;

       printk(KERN_INFO "%s: \n",__func__);

       pp = of_find_property(dev->dev.of_node, "testdata", NULL);
       if (pp)
              printk(KERN_INFO "%s: %d:%s \n",__func__,pp->length,(char *)pp->value);

       dump_stack();  // 打印堆棧

    return 0;
}

編譯運行后如下,可以看到zsl_drv.probe會被調(diào)用到,并且能拿到設(shè)備樹里的testdata屬性。

Platform驅(qū)動和設(shè)備的關(guān)系

根據(jù)堆棧打印跟蹤代碼,調(diào)用調(diào)用關(guān)系如下

platform_driver_register
    driver_register 
        bus_add_driver   
            klist_add_tail
            driver_attach
                driver_match_device(struct device *dev, void *data)=platform_match(struct device *dev, struct device_driver *drv) //找dev
                driver_probe_device
                    really_probe
                        dev->bus->probe=platform_probe
                            drv->probe=zsl_drv_probe

Driver注冊時通過bus_add_driver將driver加入總線(klist_add_tail到總線的driver列表),觸發(fā)driver_attach,遍歷總線的device列表,通過platform_match匹配已有設(shè)備。

基本就是按順序?qū)υO(shè)備樹、id_table name的字符串匹配。匹配成功后,通過really_probe調(diào)用總線默認(rèn)的platform_probe,最終執(zhí)行driver的probe函數(shù)。

platform_device_register
    platform_device_add
        device_add
            bus_probe_device
                device_initial_probe=__device_attach
                    __device_attach_driver
                        driver_match_device(struct device *dev, void *data)=platform_match(struct device *dev, struct device_driver *drv)  //找drv
                        driver_probe_device
                            really_probe
                                dev->bus->probe=platform_probe
                                    drv->probe=zsl_drv_probe
            klist_add_tail

Device注冊時通過device_add將device加入總線(klist_add_tail到總線的device列表)觸發(fā)bus_probe_device,遍歷總線的driver列表,通過platform_match匹配已有驅(qū)動,匹配成功則調(diào)用driver的probe函數(shù)。

這種雙向注冊機制確保了無論driver和device的注冊順序如何,都能正確觸發(fā)匹配和初始化。

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • ubuntu下使用sublime text時如何完美輸入中文

    ubuntu下使用sublime text時如何完美輸入中文

    網(wǎng)上的很多方法都不能讓ubuntu下的sublime輸入中文,使用Input Helper也很是別扭,這個方法是某大神通過啟動sublime程序前運行腳本修改sublime來實現(xiàn)中文輸入。
    2015-12-12
  • Linux如何查看進(jìn)程棧信息示例

    Linux如何查看進(jìn)程棧信息示例

    本篇文章主要介紹了Linux如何查看進(jìn)程棧信息示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • Linux檢測遠(yuǎn)程服務(wù)器端口的幾種方法

    Linux檢測遠(yuǎn)程服務(wù)器端口的幾種方法

    作為系統(tǒng)管理員、網(wǎng)絡(luò)工程師或應(yīng)用程序開發(fā)人員,需要檢查遠(yuǎn)程服務(wù)器上的端口是否打開,以便您可以判斷所檢查的服務(wù)是否正在運行,所以本文給大家介紹了Linux檢測遠(yuǎn)程服務(wù)器端口的幾種方法,需要的朋友可以參考下
    2024-06-06
  • 關(guān)于linux分區(qū),文件系統(tǒng),目錄結(jié)構(gòu)的概述

    關(guān)于linux分區(qū),文件系統(tǒng),目錄結(jié)構(gòu)的概述

    下面小編就為大家?guī)硪黄P(guān)于linux分區(qū),文件系統(tǒng),目錄結(jié)構(gòu)的概述。小編覺得挺不錯的?,F(xiàn)在就分享給大家。也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • linux常用命令之zip/unzip命令(壓縮文件/解壓縮文件)詳解

    linux常用命令之zip/unzip命令(壓縮文件/解壓縮文件)詳解

    這篇文章主要介紹了linux常用命令之zip/unzip命令(壓縮文件/解壓縮文件),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • Apache 新站點目錄配置 SELinux 的方法

    Apache 新站點目錄配置 SELinux 的方法

    本文詳細(xì)介紹了如何使用SELinux保護(hù)Apache新站點目錄,包括確定默認(rèn)上下文、創(chuàng)建和設(shè)置新目錄的上下文、允許網(wǎng)絡(luò)連接以及驗證配置,感興趣的朋友跟隨小編一起看看吧
    2024-11-11
  • Linux如何查看、修改文件讀寫權(quán)限

    Linux如何查看、修改文件讀寫權(quán)限

    本文介紹了Linux文件權(quán)限的基本概念和查看、修改權(quán)限的方法,通過解析權(quán)限字符串(如"drwxrwxrwx")和使用chmod命令,可以詳細(xì)設(shè)置用戶、組和其他人的讀、寫、執(zhí)行權(quán)限
    2024-12-12
  • 關(guān)于安裝LNMP集成包后上傳圖片報500錯誤的解決方法

    關(guān)于安裝LNMP集成包后上傳圖片報500錯誤的解決方法

    這篇文章主要給大家介紹了關(guān)于安裝LNMP集成包后上傳圖片報500錯誤的解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-01-01
  • Linux自動化構(gòu)建工具-make/Make?le使用解讀

    Linux自動化構(gòu)建工具-make/Make?le使用解讀

    Linux項目自動化構(gòu)建工具M(jìn)ake/Makefile指南,涵蓋基礎(chǔ)語法、高級特性及實戰(zhàn)技巧,如變量、偽目標(biāo)、模式規(guī)則、條件編譯等,提升開發(fā)效率
    2025-09-09
  • 簡單談?wù)刢entos7中配置php

    簡單談?wù)刢entos7中配置php

    windows server2008下搭建PHP運行環(huán)境,用IIS+PHP或者phpstudy,或wamp。今天試了試,在linux下搭建php運行環(huán)境。感覺還不錯。
    2018-06-06

最新評論

福贡县| 泽州县| 福安市| 合肥市| 曲周县| 华宁县| 丰台区| 松原市| 凌云县| 新河县| 高淳县| 石渠县| 霸州市| 容城县| 喜德县| 盐边县| 大港区| 新平| 精河县| 澄江县| 三门峡市| 清原| 马鞍山市| 蓬安县| 渭源县| 新竹市| 湘潭市| 永德县| 井冈山市| 和平区| 五台县| 鹰潭市| 富源县| 临澧县| 孟村| 临桂县| 珲春市| 威信县| 泌阳县| 文成县| 肥城市|