找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3803|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

sysfs platform總線

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:60266 發(fā)表于 2014-8-18 02:25 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
sysfs 文件系統(tǒng)linux2.6內(nèi)核引入sysfs文件系統(tǒng),sysfs可以看成與proc,devfs和devpty同類別的文件系統(tǒng),該文件系統(tǒng)是虛擬的文件系統(tǒng),可以更方便對系統(tǒng)設(shè)備進行管理。它可以產(chǎn)生一個包含所有系統(tǒng)硬件層次視圖,與提供進程和狀態(tài)信息的proc文件系統(tǒng)十分類似。sysfs把連接在系統(tǒng)上的設(shè)備和總線組織成為一個分級的文件,它們可以由用戶空間存取,向用戶空間導(dǎo)出內(nèi)核的數(shù)據(jù)結(jié)構(gòu)以及它們的屬性。sysfs的一個目的就是展示設(shè)備驅(qū)動模型中各組件的層次關(guān)系,其頂級目錄包括block,bus,drivers,class,power和firmware等.

它把實際連接到系統(tǒng)上的設(shè)備和總線組織成一個分級的文件,用戶空間的程序同樣可以利用這些信息以實現(xiàn)和內(nèi)核的交互,該文件系統(tǒng)是當(dāng)前系統(tǒng)上實際設(shè)備樹的一個直觀反應(yīng),它是通過kobject子系統(tǒng)來建立這個信息的,當(dāng)一個kobject被創(chuàng)建的時候,對應(yīng)的文件和目錄也就被創(chuàng)建了,位于 /sys下的相關(guān)目錄下,既然每個設(shè)備在sysfs中都有唯一對應(yīng)的目錄,那么也就可以被用戶空間讀寫了。你可能根本沒有去關(guān)心過sysfs文件系統(tǒng)的掛載過程,它是這樣被掛載的。mount -t sysfs sysfs /sys
sysfs是一個特殊文件系統(tǒng),并沒有一個實際存放文件的介質(zhì)。sysfs的信息來源是kobject層次結(jié)構(gòu),讀一個sysfs文件,就是動態(tài)的從kobject結(jié)構(gòu)提取信息,生成文件。重啟后里面的信息當(dāng)然就沒了
sysfs文件系統(tǒng)與kobject結(jié)構(gòu)緊密關(guān)聯(lián),每個在內(nèi)核中注冊的kobject對象都對應(yīng)于sysfs文件系統(tǒng)中的一個目錄。Kobject 是Linux 2.6引入的新的設(shè)備管理機制,在內(nèi)核中由struct kobject表示。通過這個數(shù)據(jù)結(jié)構(gòu)使所有設(shè)備在底層都具有統(tǒng)一的接口,kobject提供基本的對象管理,是構(gòu)成Linux2.6設(shè)備模型的核心結(jié)構(gòu),Kobject是組成設(shè)備模型的基本結(jié)構(gòu)。類似于C++中的基類,它嵌入于更大的對象的對象中,用來描述設(shè)備模型的組件。如bus,devices, drivers 等。都是通過kobject連接起來了,形成了一個樹狀結(jié)構(gòu)。這個樹狀結(jié)構(gòu)就與/sys向?qū)?yīng)。
sysfs就是利用VFS的接口去讀寫kobject的層次結(jié)構(gòu),建立起來的文件系統(tǒng)。 kobject的層次結(jié)構(gòu)的注冊與注銷XX_register()形成的。文件系統(tǒng)是個很模糊廣泛的概念, linux把所有的資源都看成是文件,讓用戶通過一個統(tǒng)一的文件系統(tǒng)操作界面,也就是同一組系統(tǒng)調(diào)用,對屬于不同文件系統(tǒng)的文件進行操作。這樣,就可以對用戶程序隱藏各種不同文件系統(tǒng)的實現(xiàn)細(xì)節(jié),為用戶程序提供了一個統(tǒng)一的,抽象的,虛擬的文件系統(tǒng)界面,這就是所謂"VFS(Virtual Filesystem Switch)"。這個抽象出來的接口就是一組函數(shù)操作。
我們要實現(xiàn)一種文件系統(tǒng)就是要實現(xiàn)VFS所定義的一系列接口,file_operations, dentry_operations, inode_operations等,供上層調(diào)用。file_operations是描述對每個具體文件的操作方法(如:讀,寫),dentry_operations結(jié)構(gòu)體指明了VFS所有目錄的操作方法, 而inode_operations提供所有結(jié)點的操作方法。
舉個例子,我們寫C程序,open(“hello.c”, O_RDONLY),它通過系統(tǒng)調(diào)用的流程是這樣的
open() -> 系統(tǒng)調(diào)用-> sys_open() -> filp_open()-> dentry_open() -> file_operations->open()         
不同的文件系統(tǒng),調(diào)用不同的file_operations->open(),在sysfs下就是sysfs_open_file()。
我們使用不同的文件系統(tǒng),就是將它們各自的文件信息都抽象到dentry和inode中去。這樣對于高層來說,我們就可以不關(guān)心底層的實現(xiàn),我們使用的都是一系列標(biāo)準(zhǔn)的函數(shù)調(diào)用。這就是VFS的精髓,實際上就是面向?qū)ο蟆?br /> 注意sysfs是典型的特殊文件。它存儲的信息都是由系統(tǒng)動態(tài)的生成的,它動態(tài)的包含了整個機器的硬件資源情況。從sysfs讀寫就相當(dāng)于向 kobject層次結(jié)構(gòu)提取數(shù)據(jù)。

Linux內(nèi)核驅(qū)動的的platform機制
虛擬總線platform簡介

 從Linux 2.6起引入了一套新的驅(qū)動管理和注冊機制:platform_device和platform_driver。Linux中大部分的設(shè)備驅(qū)動,都可以使用這套機制,設(shè)備用platform_device表示,驅(qū)動用platform_driver進行注冊。
 Linux platform. driver機制和傳統(tǒng)的device driver 機制(通過driver_register函數(shù)進行注冊)相比,一個十分明顯的優(yōu)勢在于platform機制將設(shè)備本身的資源注冊進內(nèi)核,由內(nèi)核統(tǒng)一管理,在驅(qū)動程序中使用這些資源時通過platform. device提供的標(biāo)準(zhǔn)接口進行申請并使用。這樣提高了驅(qū)動和資源管理的獨立性,并且擁有較好的可移植性和安全性(這些標(biāo)準(zhǔn)接口是安全的)。platform機制的本身使用并不復(fù)雜,由兩部分組成:platform_device和platfrom_driver。通過platform機制開發(fā)底層設(shè)備驅(qū)動的大致流程如圖所示。


platform_device簡介

linux發(fā)明的platform虛擬總線,相應(yīng)的設(shè)備叫做
platform_device,相應(yīng)的驅(qū)動叫做
platfrom_driver。

    platform_device結(jié)構(gòu)體描述設(shè)備的名稱、資源信息等。該結(jié)構(gòu)被定include/linux/platform_device.h中,     定義的結(jié)構(gòu)體原型如下:

        struct platform_device {

               const char * name;    //定義平臺設(shè)備的名稱

               int id;

               struct device dev;

               u32 num_resources;

               struct resource * resource; //定義平臺設(shè)備的資源。

        };

    最重要的一個成員struct resource * resource。struct resource被定義在include/linux/ioport.h中,定義原型如下:

       struct resource {

               resource_size_t start;  //定義資源的起始地址

               resource_size_t end;  //定義資源的結(jié)束地址

               const char *name;    //定義資源的名稱

               unsigned long flags; //定義資源的類型,比如MEM,IO,IRQ,DMA類型

               struct resource *parent, *sibling, *child;  //資源鏈表指針

        };

    以RTC驅(qū)動為例(為什么用RTC,RTC是一個標(biāo)準(zhǔn)的plartform device,機制是相同的,但是相對比較簡單)
    在arch/arm/mach-sep4020/devices.c中加入rtc的plartform_device結(jié)構(gòu)體和resources結(jié)構(gòu)體:
        static struct resource sep4020_rtc_resource[] = {
              [0] = { .start = RTC_BASE_V,
                      .end   = RTC_BASE_V+ 0x2f,
                      .flags = IORESOURCE_MEM,
                    }
              [1] = {
                      .start = INTSRC_RTC,
                      .end   = INTSRC_RTC,
                      .flags = IORESOURCE_IRQ,
                    }
        };
        struct platform_device sep4020_device_rtc = {
              .name            = "sep4020_rtc",
              .id              = -1,
              .num_resources   = ARRAY_SIZE(sep4020_rtc_resource),
             .resource        = sep4020_rtc_resource,
        };   
    然后再通過4020.c文件中的__initdata設(shè)備數(shù)組將這個plartform_device結(jié)構(gòu)體注冊進去了:
        static struct platform_device *devices[] __initdata = {
               &serial_device,
             &sep4020_device_rtc,
               &epson_ohci_device,
               &sep4020_device_usbgadget
        };  
    platform_add_devices(devices, ARRAY_SIZE(devices)); 通過調(diào)用platform_add_devices()向系統(tǒng)中添加該設(shè)備了,該函數(shù)內(nèi)部調(diào)用platform_device_register( )進行設(shè)備注冊。要注意的是,這里的platform_device設(shè)備的注冊過程必須在相應(yīng)設(shè)備驅(qū)動加載之前被調(diào)用,即執(zhí)行platform_driver_register()之前,原因是驅(qū)動注冊時需要匹配內(nèi)核中所有已注冊的設(shè)備名。(后面會詳細(xì)介紹device和driver之間是如何通過注冊的名字進行連接的)
                                                           platform_driver簡介

   platform_driver結(jié)構(gòu)體的原型定義,在include/linux/platform_device.h中,代碼如下:

         struct platform_driver {
             int (*probe)(struct platform_device *);
             int (*remove)(struct platform_device *);
             void (*shutdown)(struct platform_device *);
             int (*suspend)(struct platform_device *, pm_message_t state);
             int (*suspend_late)(struct platform_device *, pm_message_t state);
             int (*resume_early)(struct platform_device *);
             int (*resume)(struct platform_device *);
             struct device_driver driver;
         };
   內(nèi)核提供的platform_driver結(jié)構(gòu)體的注冊函數(shù)為platform_driver_register(),
   其原型定義在driver/base/platform.c文件中,具體實現(xiàn)代碼如下:
         int platform_driver_register(struct platform_driver *drv)
         {
             drv->driver.bus = &platform_bus_type;
             if (drv->probe)  
                 drv->driver.probe = platform_drv_probe;
             if (drv->remove)
                 drv->driver.remove = platform_drv_remove;
             if (drv->shutdown)
                 drv->driver.shutdown = platform_drv_shutdown;
             if (drv->suspend)
                 drv->driver.suspend = platform_drv_suspend;
             if (drv->resume)
                 drv->driver.resume = platform_drv_resume;
             return driver_register(&drv->driver);
         }
    總結(jié),通常情況下只要和內(nèi)核本身運行依賴性不大的外圍設(shè)備,相對獨立的,擁有各自獨自的資源(地址總線和IRQs),都可以用platform_driver實現(xiàn)。如:LCD,網(wǎng)卡、USB、UART等,都可以用platfrom_driver寫,而timer,irq等小系統(tǒng)之內(nèi)的設(shè)備則最好不用platfrom_driver機制。






分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表