國嵌深入班-塊設備驅動程序設計


塊設備是需要分扇區的


(req->sector + req->current_nr_sectors) <<9:每個扇區是512個字節所以需要左移9位算出扇區的大小


RAMDISK,取內存中的一塊出來模擬塊設備的卡的讀寫操作


#define SIMP_BLKDEV_DEVICEMAJOR COMPAQ_SMART2_MAJOR
#define SIMP_BLKDEV_DISKNAME 	"simp_blkdev"
#define SIMP_BLKDEV_BYTES 16*1024*1024

static struct request_queue * simp_blkdev_queue;
static struct gendisk * simp_blkdev_disk;
unsigned char simp_blkdev_data[SIMP_BLKDEV_BYTES];

static void simp_blkdev_do_request(struct request_queue *q)
{	Struct request *req;
	While((req=elv_next_request(q)) != NULL){
		If((req->sector + req->current_nr_sectors) <<9) > SIMP_BLKDEV_TYTES{
		Printk(KERN_ERR_SIMP_BLKDEV_DISKNAME”:bad request :block=%11u,count=%u\n”,
		(unsigned long long)req->sector,req->current_ar_sectors);
		End_request(req,0)
		Continue;
  	}
  	Switch(rq_data_dir(req)){
 	Case READ:
  		Memcpy(req->buffer, simp_blkdev_data + (req->sector <<9),
			 req->current_nr_sectors<<9);
  		End_request(req,1);
  	Break;
  	Case WRITE:
  		Memcpy(simp_blkdev_data + (req->sector <<9), 
			req->buffer,req->current_nr_sectors<<9);
  	End_request(req,1);
  		Break;
  	Default:
  		Break;
  	}
	}
}

struct block_device_operations simp_blkdev_fops = {
	.owner = THIS_MODULE,
};

static int __init simp_blkdev_init(void)
{
	int ret;
	simp_blkdev_queue = blk_init_queue(simp_blkdev_do_request,NULL);
	if(!simp_blkdev_queue){
		ret = -ENOMEM;
		goto err_init_queue;
	}
	simp_blkdev_disk = alloc_disk(1);
	if(!simp_blkdev_disk){
		ret = -ENOMEM;
		goto err_alloc_disk;
	}

	strcpy(simp_blkdev_disk->disk_name, SIMP_BLKDEV_DISKNAME);
	simp_blkdev_disk->major = SIMP_BLKDEV_DEVICEMAJOR;
	simp_blkdev_disk->first_minor = 0;
	simp_blkdev_disk->fops = &simp_blkdev_fops;
	simp_bldkev_disk->queue = simp_blkdev_queue;
	set_capacity(simp_blkdev_disk, SIMP_BLKDEV_BYTES >>9 );
	add_disk(simp_blkdev_disk);

	return 0;

err_alloc_disk:
	blk_cleanup_queue(simp_blkdev_queue);
err_init_queue:
	return ret;
}

static void __exit simp_blkdev_exit(void){
	del_gendisk(simp_blkdev_disk);
	put_disk(simp_blkdev_disk);
	blk_cleanup_queue(simp_blkdev_queue);
}

module_init(simp_blkdev_init);
module_exit(simp_blkdev_exit);





應該考慮,frn和__make_request兩個函數的關係

這裏塊設備I/O請求可以是,對某個扇區某塊區域的請求




bi_io_vec更多是關於來自用戶的信息內容


static int simp_blkdev_make_request(struct request_queue *q, struct bio * bio)
{
	struct bio_vec *bvec;
	int i;
	void * dsk_mem;

	if((bio->bi_sector<<9) + bio->bi_size>SIMP_BLKDEV_BYTES){
		printk(KERN_ERR SIMP_BLKDEV_DISKNAME":bad request:block=%11u,count = %u\n"),
		(unsigned long long )bio->bi_sector,bio->bi_size);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
		bio_endio(bio,0,-EIO);
#else
		bio_endio(bio,-EIO);
#endif
		return 0;
	}
	dsk_mem = simp_blkdev_data + (bio->bi-sector <<9);
	
	bio_for_each_segment(bvec, bio, i){
		void * iovec_mem;
		
		switch(bio_rw(bio)):{
		case READ:
		case READA:
			iovec_mem = kmap(bvec->bv_page) + bvec->bv_offset;//因爲操作的是頁指針所以需要映射
			memcpy(iovec_mem, dsk_mem, bvec->bv_len);
			kunmap(bvec->bv_page);
			break;
		case WRITE:	
			iovec_mem = kmap(bvec->bv_page) + bvec->bv_offset;
			memcpy(dsk_mem, iovec_mem, bvec->bv_len);
			kunmap(bvec->bv_page);
			break;
		default:
			printk(KERN_ERR SIMP_BLKDEV_DISKNAME) ":unknown value bio_rw :%		

		lu\n",bio_rw(bio));
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
			bio_endio(bio,0,-EIO);
#else
			bio_endio(bio,-EIO);
#endif
		
			return 0;

		}
	}

}

static int __init simp_blkdev_init(void)
{
	int ret;
	simp_blkdev_queue = blk_alloc_queue(GFP_KERNEL);
	if(!simp_blkdev_queue){
		ret = -ENOMEM;
		goto err_init_queue;
	}

	blk_queue_make_request(simp_blkdev_queue,simp_blkdev_make,request); //這個和第一段程序不同的地方在於blk_init_queue內部先找到__make_request,然後再找到simp_blkdev_do_request;而這裏是直接給隊列分配處理函數simp_blkdev_make
	simp_blkdev_disk = alloc_disk(1);
	...
	...
	...
	return ret;
}


幾個代碼樹結構:

\blk_init_queue(rfn,lock)
    \blk_init_queue_node(rfn,lock,-1)
        \q->request_fn = rfn;
        \blk_queue_make_request(q,__make_request)
            \q->make_request_fn=__make_request;


blk_init_queue是和blk_cleanup_queue搭配使用的


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章