亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 1040 | 回復(fù): 0
打印 上一主題 下一主題

linux設(shè)備模型深探(2) [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2009-06-07 19:30 |只看該作者 |倒序?yàn)g覽

                               
v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}

  Normal
  0
  
  7.8 磅
  0
  2
  
  false
  false
  false
  
   
   
   
   
   
   
   
   
   
   
   
   
  
  MicrosoftInternetExplorer4



/* Style Definitions */
table.MsoNormalTable
        {mso-style-name:普通表格;
        mso-tstyle-rowband-size:0;
        mso-tstyle-colband-size:0;
        mso-style-noshow:yes;
        mso-style-parent:"";
        mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
        mso-para-margin:0cm;
        mso-para-margin-bottom:.0001pt;
        mso-pagination:widow-orphan;
        font-size:10.0pt;
        font-family:"Times New Roman";
        mso-fareast-font-family:"Times New Roman";
        mso-ansi-language:#0400;
        mso-fareast-language:#0400;
        mso-bidi-language:#0400;}
在前面一篇
linux設(shè)備模型深探(1)
我們詳細(xì)了解了底層元素kset,kobject,ktype之間的關(guān)系后,本節(jié)講解下驅(qū)動模型中另外幾個概念(bus、driver、device)為后面具體分析特定驅(qū)動(platform,pci)模型打個基礎(chǔ)。

BUS
在設(shè)備模型中,所有的device都是通過總線bus 連接,這里的bus包括通常意義的總線如usb,pci,也包括虛擬的platform總線。
[root@wangp bus]#
pwd
/sys/bus
[root@wangp bus]#
ls
ac97  acpi
bluetooth  gameport  i2c
ide  pci  pci_express
pcmcia  platform  pnp  scsi  serio  usb
[root@wangp
platform]# pwd
/sys/bus/platform
[root@wangp
platform]# ls
devices  drivers

struct bus_type {
       const
char              * name;
       struct
module         * owner;

       struct
kset             subsys;
       struct kset             drivers;
       struct
kset             devices;
       struct
klist              klist_devices;
       struct
klist              klist_drivers;

       struct
blocking_notifier_head bus_notifier;

       struct
bus_attribute * bus_attrs;
       struct
device_attribute    * dev_attrs;
       struct
driver_attribute     * drv_attrs;

       int           (*match)(struct device * dev, struct
device_driver * drv);
       int           (*uevent)(struct device *dev, struct
kobj_uevent_env *env);
       int           (*probe)(struct device * dev);
       int           (*remove)(struct device * dev);
       void         (*shutdown)(struct device * dev);

       int
(*suspend)(struct device * dev, pm_message_t state);
       int
(*suspend_late)(struct device * dev, pm_message_t state);
       int
(*resume_early)(struct device * dev);
       int
(*resume)(struct device * dev);

       unsigned
int drivers_autoprobe:1;
};

name是總線的名字,每個總線下都有自己的子系統(tǒng),其中包含2個kset,deviece和driver,分別代表已知總線的驅(qū)動和插入總線的設(shè)備
如platform總線的聲明如下:

struct bus_type
platform_bus_type = {
       .name             =
"platform",
       .dev_attrs       = platform_dev_attrs,
       .match            =
platform_match,
       .uevent          =
platform_uevent,
       .suspend  =
platform_suspend,
       .suspend_late  = platform_suspend_late,
       .resume_early  = platform_resume_early,
       .resume          =
platform_resume,
};

只有很少的bus_type成員需要初始化,大部分交給kernel來處理


關(guān)于總線的操作常用的如下:
int
bus_register(struct bus_type * bus);
void
bus_unregister(struct bus_type * bus);
/* iterator helpers
for buses */

列舉總線上從start之后的每個設(shè)備,并進(jìn)行fn操作,通常用途是對bus上的設(shè)備和驅(qū)動進(jìn)行綁定
int
bus_for_each_dev(struct bus_type * bus, struct device * start, void * data, int
(*fn)(struct device *, void *));

int
driver_attach(struct device_driver * drv)
{
       return bus_for_each_dev(drv->bus,
NULL, drv, __driver_attach);
}

static int
__driver_attach(struct device * dev, void * data)
{
       struct device_driver * drv = data;

       /*
        *
Lock device and try to bind to it. We drop the error
        *
here and always return 0, because we need to keep trying
        *
to bind to devices and some drivers will return an error
        *
simply if it didn't support the device.
        *
        *
driver_probe_device() will spit a warning if there
        *
is an error.
        */

       if (dev->parent)      /* Needed for USB */
              down(&dev->parent->sem);
       down(&dev->sem);
       if (!dev->driver)
              driver_probe_device(drv, dev);
       up(&dev->sem);
       if (dev->parent)
              up(&dev->parent->sem);

       return 0;
}

幾乎linux設(shè)備模型的每一層都提供了添加屬性的函數(shù),總線也不例外
struct bus_attribute
{
       struct attribute       attr;
       ssize_t (*show)(struct bus_type *, char *
buf); //顯示屬性
       ssize_t (*store)(struct bus_type *, const
char * buf, size_t count); //設(shè)置屬性
};
創(chuàng)建屬于一個總線的屬性使用(在模塊的加載時間完成)
int  bus_create_file(struct bus_type *,struct
bus_attribute *);
void
bus_remove_file(struct bus_type *, struct bus_attribute *);

在說明下bus在sysfs里面的結(jié)構(gòu),剛才已經(jīng)講過,bus_type中有2個kset結(jié)構(gòu)對應(yīng)于device和driver,也就是說每個bus下面都會有device何driver2個文件夾。

首先在總線上注冊的驅(qū)動會得到一個文件夾driver,如platform驅(qū)動
[root@wangp
platform]# pwd
/sys/bus/platform
[root@wangp
platform]# ls
devices  drivers
[root@wangp
drivers]# pwd
/sys/bus/platform/drivers
[root@wangp
drivers]# ls
i8042  pcspkr
serial8250  vesafb

而任何在總線/sys/bus/xxx/上發(fā)現(xiàn)的設(shè)備會得到一個symlink(符號鏈接)即/sys/bus/xxx/device指向/sys/device/xxx下面的文件夾
[root@wangp
devices]# pwd
/sys/bus/platform/devices
[root@wangp
devices]# ls -l
total 0
lrwxrwxrwx 1 root
root 0 Jun  6 10:37 bluetooth ->
../../../devices/platform/bluetooth
lrwxrwxrwx 1 root
root 0 Jun  6 10:37 floppy.0 ->
../../../devices/platform/floppy.0
lrwxrwxrwx 1 root
root 0 Jun  6 10:37 i8042 ->
../../../devices/platform/i8042
lrwxrwxrwx 1 root
root 0 Jun  6 10:37 pcspkr ->
../../../devices/platform/pcspkr
lrwxrwxrwx 1 root
root 0 Jun  6 10:37 serial8250 ->
../../../devices/platform/serial8250
lrwxrwxrwx 1 root
root 0 Jun  6 10:37 vesafb.0 ->
../../../devices/platform/vesafb.0


DEVICE
struct device {
       struct klist              klist_children;
       struct klist_node     knode_parent;        /*
node in sibling list */
       struct klist_node     knode_driver;
       struct klist_node     knode_bus;
       struct device          *parent;  //該設(shè)備所屬的設(shè)備

       struct kobject kobj;
       char bus_id[BUS_ID_SIZE];     /* position on parent bus */
       struct device_type  *type;
       unsigned         is_registered:1;
       unsigned         uevent_suppress:1;

       struct semaphore    sem; /* semaphore to
synchronize calls to
                                    * its driver.
                                    */

       struct bus_type      * bus;             /* type
of bus device is on */
       struct device_driver *driver;    /* which driver has allocated this  device */
       void         *driver_data;   /* data private to the driver */
       void         *platform_data;      /* Platform specific data, device  core doesn't touch it */
       struct dev_pm_info power;

#ifdef CONFIG_NUMA
       int           numa_node;    /* NUMA node this device is close to */
#endif
       u64         *dma_mask;    /* dma mask (if dma'able device) */
       u64         coherent_dma_mask;/*
Like dma_mask, but for
                                        alloc_coherent mappings as
                                        not all hardware supports
                                        64 bit addresses for consistent
                                        allocations such descriptors. */

       struct list_head       dma_pools;      /* dma
pools (if dma'ble) */

       struct dma_coherent_mem     *dma_mem; /* internal for coherent mem   override */
       /* arch specific additions */
       struct dev_archdata archdata;

       spinlock_t        devres_lock;
       struct list_head       devres_head;

       /* class_device migration path */
       struct list_head       node;
       struct class             *class;
       dev_t                    devt;              /* dev_t, creates the sysfs
"dev" */
       struct attribute_group    **groups;       /*
optional groups */

       void  (*release)(struct
device * dev);
};
這個結(jié)構(gòu)相當(dāng)于一個基類,對于基于特定總線的設(shè)備,會派生出特定的device結(jié)構(gòu)(linux的驅(qū)動模型有很多結(jié)構(gòu)都可以基于類來看待)

struct
platform_device {
       const char       * name;
       int           id;
       struct device   dev;
       u32         num_resources;
       struct resource       * resource;
};

一個總線設(shè)備用如下函數(shù)注冊(注冊總線類型)
int
device_register(struct device *dev)
{
       device_initialize(dev);
       return device_add(dev);
}
以完成parent name bus_id bus幾個成員的初始化,注冊后可以在/sys/devices下面看到
void
device_unregister(struct device *dev);

同時和其相關(guān)的屬性為
struct
device_attribute {
       struct attribute       attr;
       ssize_t (*show)(struct device *dev,
struct device_attribute *attr,char *buf);
       ssize_t (*store)(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count);
};
int
device_create_file(struct device *device,struct device_attribute * entry);
device_remove_file(struct
device * dev, struct device_attribute * attr);
以下完成一個總線設(shè)備的注冊:
static void
simple_bus_release(struct device *dev)
{
       printk("simple bus release\n");
}
struct device
simple_bus = {
       .bus_id ="simple_bus",
       .release = simple_bus_release
}

ret =
device_register(&simple_bus);
if(ret)
pritnk("unable
to register simple_bus\n");
完成注冊后,simple_bus就可以再sysfs中/sys/devices下面看見,任何掛載這個bus上的device都會在/sys/devices/simple_bus下看到

DEVICE_DRIVER

struct device_driver
{
       const char              * name;//在sysfs下顯示
       struct bus_type             * bus;

       struct kobject         kobj;
       struct klist              klist_devices;
       struct klist_node     knode_bus;

       struct module         * owner;
       const char             * mod_name;  /* used
for built-in modules */
       struct module_kobject    * mkobj;

       int    (*probe)  (struct device * dev);
       int    (*remove)       (struct device * dev);
       void  (*shutdown)   (struct device * dev);
       int    (*suspend)      (struct device * dev, pm_message_t state);
       int    (*resume)       (struct device * dev);
};
由于大多數(shù)驅(qū)動都會帶有特有的針對某種特定總線的信息,因此一般都是基于device_driver來派生出自己
特有的驅(qū)動,如
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;
};
比較xxx_driver 和device_driver我們可以發(fā)現(xiàn),結(jié)構(gòu)體所帶的方法基本相同,在具體應(yīng)該用的時候是可以轉(zhuǎn)換的。

驅(qū)動的注冊
int
driver_register(struct device_driver * drv);
void
driver_unregister(struct device_driver * drv);
而大多數(shù)驅(qū)動會調(diào)用針對特定總線的諸如platform_driver_register,pci_driver_register之類的函數(shù)去注冊

總線(bus)可以掛接一類設(shè)備(device)
驅(qū)動(driver)可以驅(qū)動一類設(shè)備(device)
因此和bus一樣,device_driver也有一個函數(shù)為某個驅(qū)動來遍歷所有設(shè)備
int
driver_for_each_dev(struct device_driver *drv, void *data,int
(*callback)(struct device *dev,void *data);
所有device_driver完成注冊后,會在/sys/bus/xxx/driver目錄下看到驅(qū)動信息

同時相應(yīng)的屬性內(nèi)容
struct
driver_attribute {
       struct attribute       attr;
       ssize_t (*show)(struct device_driver *,
char * buf);
       ssize_t (*store)(struct device_driver *,
const char * buf, size_t count);
};
int  driver_create_file(struct device_driver
*,struct driver_attribute *);
void
driver_remove_file(struct device_driver *, struct driver_attribute *);

說了這么多,現(xiàn)在來理一理kobject kset,subsys,sysfs,bus之間的關(guān)系



  
  
  
  
  
  
  
  
  
  
  
  




上圖反映了繼承體系的一個基本結(jié)構(gòu),kset是一組相同的kobject的集合,kernel可以通過跟蹤kset來跟蹤所用的特定類型設(shè)備,platform、pci、i2c等,kset起到連接作用將設(shè)備模型和sysfs聯(lián)系在一起。每個kset自身都包含一個kobject,這個kobject將作為很多其他的kobject的父類,從sys上看,某個kobject的父類是某個目錄,那么它就是那個目錄的子目錄,parent指針可以代表目錄層次,這樣典型的設(shè)備模型層次就建立起來了,從面向?qū)ο蟮挠^點(diǎn)看,kset是頂層的容器類,kset繼承他自己的kobject,并且可以當(dāng)做kobject來處理


如圖:kset把它的子類kobject放在鏈表里面,kset子類鏈表里面那些kobject的kset指針指向上面的kset,parent指向父類。

struct kobject {
       const char              * k_name;
       struct kref              kref;
       struct list_head       entry;
       struct kobject         * parent;
       struct kset             * kset;
       struct kobj_type     * ktype;
       struct sysfs_dirent   * sd;
};

struct kset {
       struct kobj_type     *ktype;
       struct list_head       list;
       spinlock_t        list_lock;
       struct kobject         kobj;
       struct kset_uevent_ops  *uevent_ops;
};



                 


有了這些基本單元,就可以派生出許多其他的新類別

了解了驅(qū)動模型的構(gòu)架后,我們就可以分析具體的驅(qū)動(platform,pci)。



               
               
               
               

本文來自ChinaUnix博客,如果查看原文請點(diǎn):http://blog.chinaunix.net/u2/72003/showart_1958091.html
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP