通常的字元裝置驅動:
①確定主裝置號major;
②構造file_opertions結構體
③註冊字元裝置registe_chrdev(組裝置號,name,0)
④建立類和裝置
⑤入口⑥出口
之前:以主裝置號為下標,在chrdevs裡找到之前註冊的file_operations
只能有255個字元裝置驅動
cd = __register_chrdev_region(major, 0, 256, name);
這樣做的結果就是向核心連續註冊了256個次裝置號,也就把major這個主裝置號下的所有次裝置號都占用了。
巨大的浪費,違背核心精神,最節約情況就是用多少註冊多少。
現在:(2.6核心)以主裝置號和次裝置號來找到file_operations
共有2的12次方乘以2的20次方個驅動。
從(主,次)到(主,次+n)都對應這個file_operation
registe_chrdev展開為:
①register_chrdev_region/alloc_chrdev_region
②cdev_init
③cdev_add
所以有了以下2個函式:
① register_chrdev_region(dev_t from, unsigned count, const char *name)
② alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)
register_chrdev_region函式:
第乙個引數dev_t from是乙個unsigned型的數,高12位表示主裝置號,低20位表示次裝置號。因此這個引數中包含了起始的次裝置號。第二個引數unsigned count表示需要註冊的連續的次裝置號的個數。最後乙個引數表示裝置或驅動的名字。
register_chrdev_region函式在呼叫之前需要確定from這個引數的值,裝置號是已知的。而alloc_chrdev_region這個函式呼叫的時候不需要知道裝置的裝置號是多少,核心會動態分配乙個給他。在分配好了之後會把裝置號寫到裝置號變數的位址,所以看到在呼叫alloc_chrdev_region這個函式的時候它的第乙個引數是裝置號變數的位址。
alloc_chrdev_region它的第二個引數是起始次裝置號,第三個引數是要註冊的次裝置號個數,最後乙個是裝置或驅動的名字。
這兩個函式最終呼叫的都是__register_chrdev_region,同時需要跟cdev_init(struct cdev *cdev, const struct file_operations *fops)和 cdev_add(struct cdev *p, dev_t dev, unsigned count)來配合使用。這2個函式的功能在以前的字元裝置驅動程式中是在register_chrdev這乙個函式中完成的,在這裡需要自己來呼叫。
register_chrdev這個函式就被完美的替代了。就可以通過控制註冊的起始次裝置號以及多少個次裝置號,實現了用多少註冊多少的目的。
1、構造乙個file_operation
/* 1. 確定主裝置號 */
static int major;
static int hello_open(struct inode *inode, struct file *file)
/* 2. 構造file_operations */
static struct file_operations hello_fops = ;
static int hello_init(void)
else
cdev_init(&hello_cdev, &hello_fops);
cdev_add(&hello_cdev, devid, hello_cnt);
#endif
cls = class_create(this_module, "hello");
class_device_create(cls, null, mkdev(major, 0), null, "hello0"); /* /dev/hello0 */
class_device_create(cls, null, mkdev(major, 1), null, "hello1"); /* /dev/hello1 */
class_device_create(cls, null, mkdev(major, 2), null, "hello2"); /* /dev/hello2 */
return 0;
}
static void hello_exit(void)
2、構造兩個file_operation
/* 1. 確定主裝置號 */
static int major;
static int hello_open(struct inode *inode, struct file *file)
static int hello2_open(struct inode *inode, struct file *file)
/* 2. 構造file_operations */
static struct file_operations hello_fops = ;
static struct file_operations hello2_fops = ;
static int hello_init(void)
else
cdev_init(&hello_cdev, &hello_fops);
cdev_add(&hello_cdev, devid, hello_cnt);
devid = mkdev(major, 2);
register_chrdev_region(devid, 1, "hello2");
cdev_init(&hello2_cdev, &hello2_fops);
cdev_add(&hello2_cdev, devid, 1);
#endif
cls = class_create(this_module, "hello");
class_device_create(cls, null, mkdev(major, 0), null, "hello0"); /* /dev/hello0 */
class_device_create(cls, null, mkdev(major, 1), null, "hello1"); /* /dev/hello1 */
class_device_create(cls, null, mkdev(major, 2), null, "hello2"); /* /dev/hello2 */
class_device_create(cls, null, mkdev(major, 3), null, "hello3"); /* /dev/hello3 */
return 0;
}
static void hello_exit(void)
makefile:
kern_dir = /work/system/linux-2.6.22.6
all:
make -c $(kern_dir) m=`pwd` modules
clean:
make -c $(kern_dir) m=`pwd` modules clean
rm -rf modules.order
obj-m += hello.o
測試**:
/*
* hello_test /dev/hello0
*/void print_usage(char *file)
int main(int argc, char **ar**)
fd = open(ar**[1], o_rdwr);
if (fd < 0)
printf("can't open %s\n", ar**[1]);
else
printf("can open %s\n", ar**[1]);
return 0;
}
裝置驅動例項 字元裝置驅動
在整個linux裝置驅動學習中,字元裝置驅動較為基礎。通過對它的學習,對裝置驅動進一步加深了解 cdev 結構體struct cdev 講下比較重要的成員變數 dev t dev 定義了32位的裝置號,其中12位是主裝置號,20位是從裝置號。獲取主裝置號 major dev t dev 獲取從裝置號...
字元裝置驅動
字元裝置驅動 概述 塊裝置 字元裝置以及網路裝置中塊裝置和網路裝置一般都會硬體配置完備,對於程式設計師而言,能夠更多操作的就是字元裝置。設定字元裝置的一般步驟 1.初始化硬體 2.定義fops file operations 3.申請cdev,掛載fops 3.加入cdev 函式cdev add 主...
字元裝置驅動
標頭檔案包含 include 變數定義 define gpgconaddr 0x56000060 硬體中斷號定義 define key1 irq irq eint5 define key2 irq irq eint3 裝置名定義 define devname mykey 主裝置號 cdev定義 需全...