| 
 
    
        
            |  #elseif (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) {
 printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
 MTD_BLOCK_MAJOR);
 return -EAGAIN;
 }
 #endif
 
 /* We fill it in at open() time. */
 for (i=0; i< MAX_MTD_DEVICES; i++) {
 mtd_sizes[i] = 0;
 mtd_blksizes[i] = BLOCK_SIZE;
 }
 init_waitqueue_head(&thr_wq);
 /* Allow the block size to default to BLOCK_SIZE. */
 blksize_size[MAJOR_NR] = mtd_blksizes;
 blk_size[MAJOR_NR] = mtd_sizes;
 
 BLK_INIT_QUEUE(BLK_DEFAULT_QUEUE(MAJOR_NR), &mtdblock_request, &mtdblock_lock);
 
 kernel_thread (mtdblock_thread, NULL, CLONE_FS|CLONE_FILES|CLONE_SIGHAND);
 return 0;
 }
 
 static void __exit cleanup_mtdblock(void)
 {
 leaving = 1;
 wake_up(&thr_wq);
 down(&thread_sem);
 #ifdef CONFIG_DEVFS_FS
 unregister_mtd_user(¬ifier);
 devfs_unregister(devfs_dir_handle);
 devfs_unregister_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME);
 #else
 unregister_blkdev(MAJOR_NR,DEVICE_NAME);
 #endif
 blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 blksize_size[MAJOR_NR] = NULL;
 blk_size[MAJOR_NR] = NULL;
 }
 
 module_init(init_mtdblock);
 module_exit(cleanup_mtdblock);
 |    从上述源代码中我们发现,块设备也以与字符设备register_chrdev、unregister_ chrdev 函数类似的方法进行设备的注册与释放: 
 
    
        
            | int register_blkdev(unsigned int major, const char *name, struct block_device_operations *bdops); int unregister_blkdev(unsigned int major, const char *name);
 |    但是,register_chrdev使用一个向 file_operations 结构的指针,而register_blkdev 则使用 block_device_operations 结构的指针,其中定义的open、release 和 ioctl 方法和字符设备的对应方法相同,但未定义 read 或者 write 操作。这是因为,所有涉及到块设备的 I/O 通常由系统进行缓冲处理。
 块驱动程序最终必须提供完成实际块 I/O 操作的机制,在 Linux 当中,用于这些 I/O 操作的方法称为"request(请求)"。在块设备的注册过程中,需要初始化request队列,这一动作通过blk_init_queue来完成, blk_init_queue函数建立队列,并将该驱动程序的 request 函数关联到队列。在模块的清除阶段,应调用 blk_cleanup_queue 函数。
   |