Procedure:
Module kernel implementation analysis process:
Analysis code
Analyze ll_rw_block for (I = 0; I <nr; I ++) {struct buffer_head * bh = bhs [I]; submit_bh (rw, bh); struct bio * bio; // use bh to construct bio (block input/output) submit_bio (rw, bio); // general construction request: use bio to construct the request generic_make_request (bio ); _ generic_make_request (bio); request_queue_t * q = bdev_get_queue (bio-> bi_bdev ); // locate the queue // call the queue's "constructor request function" ret = q-> make_request_fn (q, bio ); // The default function is _ make_request // first try to merge elv_merge (q, & req, bio); // If the merge fails, use bio to construct the request init_request_from_bio (req, bio); // put the request into the queue add_request (q, req); // execution queue _ generic_unplug_device (q ); // call the queue's "processing function" q-> request_fn (q );
Driver code implementation:
Ramblock. c
/* Reference: * drivers \ block \ xd. c * drivers \ block \ z2ram. c */# include <linux/module. h> # include <linux/errno. h> # include <linux/interrupt. h> # include <linux/mm. h> # include <linux/fs. h> # include <linux/kernel. h> # include <linux/timer. h> # include <linux/genhd. h> # include <linux/hdreg. h> # include <linux/ioport. h> # include <linux/init. h> # include <linux/wait. h> # include <linux/blkdev. h> # include <linux/blkpg. h> # include <l Inux/delay. h> # include <linux/io. h> # include <asm/system. h> # include <asm/uaccess. h> # include <asm/dma. h> static struct gendisk * ramblock_disk; static request_queue_t * ramblock_queue; static int major; static DEFINE_SPINLOCK (ramblock_lock); # define RAMBLOCK_SIZE (1024*1024) static unsigned char * ramblock_buf; // provide the Disk Property Information static int ramblock_getgeo (struct block_device * bdev, struct hd_geometry * geo) {/* capacity = he Ads * cylinders * sectors * 512 */geo-> heads = 2; // geo-> cylinders = 32; // Number of cylinders geo-> sectors = RAMBLOCK_SIZE/2/32/512; // return 0;} static struct block_device_operations ramblock_fops = {. owner = THIS_MODULE ,. getgeo = ramblock_getgeo,}; static void do_ramblock_request (request_queue_t * q) {static int r_cnt = 0; static int w_cnt = 0; struct request * req; // printk ("do_ramblock_request % d \ n", ++ c Nt); while (req = elv_next_request (q ))! = NULL) {/* three elements of data transmission: source, destination, length * // * source/destination: */unsigned long offset = req-> sector * 512; /* destination/Source: * // req-> buffer/* length: */unsigned long len = req-> current_nr_sectors * 512; if (rq_data_dir (req) = READ) {// printk ("do_ramblock_request read % d \ n", ++ r_cnt); memcpy (req-> buffer, ramblock_buf + offset, len );} else {// printk ("do_ramblock_request write % d \ n", ++ w_cnt); memcpy (ramblock_buf + offset, req-> buffer, len);} end_request (req, 1) ;}} static int ramblock_init (void) {/* 1. allocate a gendisk struct */ramblock_disk = alloc_disk (16);/* Number of device numbers: Number of partitions + 1 * // * 2. set * // * 2.1 allocate/set the queue: Provide read/write capability */ramblock_queue = blk_init_queue (do_ramblock_request, & ramblock_lock); ramblock_disk-> queue = ramblock_queue;/* 2.2 set other attributes: for example, capacity */major = register_blkdev (0, "ramblock");/* cat/proc/devices */ramblock_disk-> major = major; ramblock_disk-> first_minor = 0; sprintf (ramblock_disk-> disk_name, "ramblock"); ramblock_disk-> fops = & ramblock_fops; set_capacity (ramblock_disk, RAMBLOCK_SIZE/512);/* 3. hardware-related operations */ramblock_buf = kzarloc (RAMBLOCK_SIZE, GFP_KERNEL);/* 4. register */add_disk (ramblock_disk); return 0;} static void ramblock_exit (void) {unregister_blkdev (major, "ramblock"); del_gendisk (ramblock_disk); put_disk (ramblock_disk ); blk_cleanup_queue (ramblock_queue); kfree (ramblock_buf);} module_init (ramblock_init); module_exit (ramblock_exit); MODULE_LICENSE ("GPL ");