年紀大的人通常會有一種感覺(實際上我還不算大),那就是年輕一代和自己的思想往往會有一些出入,小弟在這里發表下個人拙見,如有看完不爽者請諒解:現在網上年輕一代不是正流行非主流文化嘛!對于一些老人家,往往喜歡對這些現象品頭論足,說起來這時代發展就這樣唄,想想我們當年,嘿嘿,就我而言吧!徹底的保守派,在很多年輕人看來,從思想或行動上看,完全是個古董那種。但俺也有自己的苦衷,一方面父母管得嚴,一方面自己生活的環境接觸的人就這樣,有什么辦法呢?于是我選擇認命,幸運的是到目前為止,活得還算瀟灑,嘿嘿(有點自戀了)。但啊,這時代究竟是時代啊!某一天又出來個新主流了,有人出生的地方,再新的思想就總會有過時的時候。中國有句話說得響亮:“與時俱進”,個人覺得挺有道理,社會生產力發展著,人的需求也在發生變化,哪個時候,沒學會玩電腦就算文盲,是吧?這個女人啊!也一樣,需求也是越來越豐富啊!市場經濟,有需求就會有提供,做新男人,也成了一種新時尚。話是這么說,但不管如何始終還是個男人,這點還沒變。
據說在Linux 2.6.18版本的內核之后,出現了一種新的管理設備文件的方法,叫:udev(userspace device management)取代我們之前看到的那種devfs管理方式。(這個我也是今天晚上有人告訴,我才知道的,悲哀的很,要知道孤陋寡聞的人是很容易被淘汰的~~怕怕,于是上官網look了下,搞了這個文章算是知識補充吧!),udev的官方文檔對它做了如下定義:udev是一種用戶空間上的應用程序,它動態地為位于/dev下的當前正被使用的設備,提供一個唯一的入口,udev將取代devfs。關于udev的優勢,網上大把資料,試問,哪個東西出來的時候沒吹上一車呢,自己seesee,不說也罷!
下面是一個是一個完整的usb驅動,有人要問了,你小子怎么老來usb,換個其他的,可以不?嘿嘿,對usb太情有獨鐘了,一想到驅動,總是到它。
與前面所說的devfs在使用上是有所區別的,結構體、使用的函數和實現步驟都存在差異,所謂差異就是說它們還是有一些相似之處的,新男人也還是男人這點還沒變。在\linux-2.6.16.20\include\linux\device.h中做如下定義:
struct class { const char * name; struct module * owner; struct subsystem subsys; struct list_head children; struct list_head interfaces; struct semaphore sem; /* locks both the children and interfaces lists */ struct class_attribute * class_attrs; struct class_device_attribute * class_dev_attrs; int (*uevent)(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size); void (*release)(struct class_device *dev); void (*class_release)(struct class *class); }; |
struct class_device { struct list_head node; struct kobject kobj; struct class * class; /* required */ dev_t devt; /* dev_t, creates the sysfs "dev" */ struct class_device_attribute *devt_attr; struct class_device_attribute uevent_attr; struct device * dev; /* not necessary, but nice to have */ void * class_data; /* class-specific data */ struct class_device *parent; /* parent of this child device, if there is one */ void (*release)(struct class_device *dev); int (*uevent)(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size); char class_id[BUS_ID_SIZE]; /* unique to this class */ }; |
對特定的設備使用特定的結構,下面兩個結構來自\linux-2.6.16.20\include\linux\usb.h
struct usb_interface { /* array of alternate settings for this interface, * stored in no particular order */ struct usb_host_interface *altsetting; struct usb_host_interface *cur_altsetting; /* the currently * active alternate setting */ unsigned num_altsetting; /* number of alternate settings */ int minor; /* minor number this interface is * bound to */ enum usb_interface_condition condition; /* state of binding */ struct device dev; /* interface specific device info */ struct class_device *class_dev; }; |
struct usb_class_driver { char *name; struct file_operations *fops; int minor_base; }; |
在創建的時候要使用到以下函數,它們在\linux-2.6.16.20\include\linux\device.h中定義如下:
extern struct class *class_create(struct module *owner, char *name);//創建一個類,返回一個class extern void class_destroy(struct class *cls);//銷毀一個類 extern struct class_device *class_device_create(struct class *cls, struct class_device *parent, dev_t devt, struct device *device, char *fmt, ...) __attribute__((format(printf,5,6)));//為類創建一個類設備,返回一個class_device extern void class_device_destroy(struct class *cls, dev_t devt);//銷毀一個類設備 |
使用過程可以是這樣的(注意:這里做了省略處理):
static struct class *usb_class; int usb_major_init(void) { usb_class = class_create(THIS_MODULE, "usb"); } void usb_major_cleanup(void) { class_destroy(usb_class); } int usb_register_dev(struct usb_interface *intf,//class_device為參 struct usb_class_driver *class_driver) { intf->class_dev = class_device_create(usb_class, NULL, MKDEV(USB_MAJOR, minor), //以主設備號和次設備號為參 &intf->dev, "%s", temp); } EXPORT_SYMBOL(usb_register_dev); void usb_deregister_dev(struct usb_interface *intf, struct usb_class_driver *class_driver) { class_device_destroy(usb_class, MKDEV(USB_MAJOR, intf->minor)); } EXPORT_SYMBOL(usb_deregister_dev); |
于是對于udev我們又可以得到一個省口水的圖:
Udev設備管理方式 |
Devfs設備管理方式 |
包含必要的頭文件 |
包含必要的頭文件 |
填充file_operations |
填充file_operations |
創建usb_class類 |
填充usb_driver |
register\deregister |
usb_register\usb_deregister |
EXPORT_SYMBOL |
module_init\ module_exit |
下面給出一個完整的代碼
來自:\linux-2.6.16.20\drivers\usb\core\file.c
#include <linux/config.h> #include <linux/module.h> #include <linux/spinlock.h> #include <linux/errno.h> #include <linux/usb.h> #include "usb.h" #define MAX_USB_MINORS 256 static struct file_operations *usb_minors[MAX_USB_MINORS]; static DEFINE_SPINLOCK(minor_lock); static int usb_open(struct inode * inode, struct file * file) { int minor = iminor(inode); struct file_operations *c; int err = -ENODEV; struct file_operations *old_fops, *new_fops = NULL; spin_lock (&minor_lock); c = usb_minors[minor]; if (!c || !(new_fops = fops_get(c))) { spin_unlock(&minor_lock); return err; } spin_unlock(&minor_lock); old_fops = file->f_op; file->f_op = new_fops; /* Curiouser and curiouser... NULL ->open() as "no device" ? */ if (file->f_op->open) err = file->f_op->open(inode,file); if (err) { fops_put(file->f_op); file->f_op = fops_get(old_fops); } fops_put(old_fops); return err; } static struct file_operations usb_fops = { .owner = THIS_MODULE, .open = usb_open, }; static struct class *usb_class; int usb_major_init(void) { int error; error = register_chrdev(USB_MAJOR, "usb", &usb_fops); if (error) { err("unable to get major %d for usb devices", USB_MAJOR); goto out; } usb_class = class_create(THIS_MODULE, "usb"); if (IS_ERR(usb_class)) { error = PTR_ERR(usb_class); err("class_create failed for usb devices"); unregister_chrdev(USB_MAJOR, "usb"); goto out; } out: return error; } void usb_major_cleanup(void) { class_destroy(usb_class); unregister_chrdev(USB_MAJOR, "usb"); } int usb_register_dev(struct usb_interface *intf, struct usb_class_driver *class_driver) { int retval = -EINVAL; int minor_base = class_driver->minor_base; int minor = 0; char name[BUS_ID_SIZE]; char *temp; #ifdef CONFIG_USB_DYNAMIC_MINORS minor_base = 0; #endif intf->minor = -1; dbg ("looking for a minor, starting at %d", minor_base); if (class_driver->fops == NULL) goto exit; spin_lock (&minor_lock); for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) { if (usb_minors[minor]) continue; usb_minors[minor] = class_driver->fops; retval = 0; break; } spin_unlock (&minor_lock); if (retval) goto exit; intf->minor = minor; /* create a usb class device for this usb interface */ snprintf(name, BUS_ID_SIZE, class_driver->name, minor - minor_base); temp = strrchr(name, '/'); if (temp && (temp[1] != 0x00)) ++temp; else temp = name; intf->class_dev = class_device_create(usb_class, NULL, MKDEV(USB_MAJOR, minor), &intf->dev, "%s", temp); if (IS_ERR(intf->class_dev)) { spin_lock (&minor_lock); usb_minors[intf->minor] = NULL; spin_unlock (&minor_lock); retval = PTR_ERR(intf->class_dev); } exit: return retval; } EXPORT_SYMBOL(usb_register_dev); void usb_deregister_dev(struct usb_interface *intf, struct usb_class_driver *class_driver) { int minor_base = class_driver->minor_base; char name[BUS_ID_SIZE]; #ifdef CONFIG_USB_DYNAMIC_MINORS minor_base = 0; #endif if (intf->minor == -1) return; dbg ("removing %d minor", intf->minor); spin_lock (&minor_lock); usb_minors[intf->minor] = NULL; spin_unlock (&minor_lock); snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base); class_device_destroy(usb_class, MKDEV(USB_MAJOR, intf->minor)); intf->class_dev = NULL; intf->minor = -1; } EXPORT_SYMBOL(usb_deregister_dev); |
從這篇文我們發現,技術是不斷變化的,換句話說,女人是善變的感情動物,請不要誤會,是感情動物:意為善于使用感情作為武器;而絕不是多情,多情是用來形容男人的嘛!對不?呵呵,胡說八道了吧~~
地震讓大伙知道:居安思危,才是生存之道。
