In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >
Share
Shulou(Shulou.com)06/01 Report--
This article will explain in detail the sample analysis on the writing of block device driver code in Linux. The editor thinks it is very practical, so I share it with you for reference. I hope you can get something after reading this article.
To separate block from fs, the designers of kernel defined request queue as a form. In other words, all fs requests for block devices will eventually be transformed into request. Therefore, for block device driver developers, dealing with request queue will master half of the block device. Of course, there are many block devices, hd, floppy, ram can be defined in this way, interested friends can find the relevant code in drivers/block to read. Students who are not so interested can take a look at our blog post and basically learn something about it. A basic concept, coupled with a simple and simple example, is enough for ordinary friends.
Without much gossip, let's take a look at how a ramdisk code driver is written, and the code comes from "going deep into the kernel mechanism of linux device drivers."
# include # define RAMHD_NAME "ramhd" # define RAMHD_MAX_DEVICE 2 # define RAMHD_MAX_PARTITIONS 4 # define RAMHD_SECTOR_SIZE 512 # define RAMHD_SECTORS 16 # define RAMHD_HEADS 4 # define RAMHD_CYLINDERS 256 # define RAMHD_SECTOR_TOTAL (RAMHD_SECTORS * RAMHD_HEADS * RAMHD_CYLINDERS) # define RAMHD_SIZE (RAMHD_SECTOR_SIZE * RAMHD_SECTOR_TOTAL) / / 8mb typedef struct {unsigned char* data Struct request_queue* queue; struct gendisk* gd;} RAMHD_DEV; static char* Sdisk [RAMHD _ MAX_DEVICE] = {NULL}; static RAMHD_DEV* Rend [RamHD _ MAX_DEVICE] = {NULL}; static dev_t ramhd_major; static int ramhd_space_init (void) {int i; int err = 0; for (I = 0; I)
< RAMHD_MAX_DEVICE; i++){ sdisk[i] = vmalloc(RAMHD_SIZE); if(!sdisk[i]){ err = -ENOMEM; return err; } memset(sdisk[i], 0, RAMHD_SIZE); } return err; } static void ramhd_space_clean(void) { int i; for(i = 0; i < RAMHD_MAX_DEVICE; i++){ vfree(sdisk[i]); } } static int ramhd_open(struct block_device* bdev, fmode_t mode) { return 0; } static int ramhd_release(struct gendisk*gd, fmode_t mode) { return 0; } static int ramhd_ioctl(struct block_device* bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { int err; struct hd_geometry geo; switch(cmd) { case HDIO_GETGEO: err = !access_ok(VERIFY_WRITE, arg, sizeof(geo)); if(err) return -EFAULT; geo.cylinders = RAMHD_CYLINDERS; geo.heads = RAMHD_HEADS; geo.sectors = RAMHD_SECTORS; geo.start = get_start_sect(bdev); if(copy_to_user((void*)arg, &geo, sizeof(geo))) return -EFAULT; return 0; } return -ENOTTY; } static struct block_device_operations ramhd_fops = { .owner = THIS_MODULE, .open = ramhd_open, .release = ramhd_release, .ioctl = ramhd_ioctl, }; static int ramhd_make_request(struct request_queue* q, struct bio* bio) { char* pRHdata; char* pBuffer; struct bio_vec* bvec; int i; int err = 0; struct block_device* bdev = bio->Bi_bdev; RAMHD_DEV* pdev = bdev- > bd_disk- > private_data; if (bio- > bi_sector * RAMHD_SECTOR_SIZE) + bio- > bi_size) > RAMHD_SIZE) {err =-EIO; return err;} pRHdata = pdev- > data + (bio- > bi_sector * RAMHD_SECTOR_SIZE); bio_for_each_segment (bvec, bio, I) {pBuffer = kmap (bvec- > bv_page) + bvec- > bv_offset Switch (bio_data_dir (bio)) {case READ: memcpy (pBuffer, pRHdata, bvec- > bv_len); flush_dcache_page (bvec- > bv_page); break; case WRITE: flush_dcache_page (bvec- > bv_page); memcpy (pRHdata, pBuffer, bvec- > bv_len); break Default: kunmap (bvec- > bv_page); goto out;} kunmap (bvec- > bv_page); pRHdata + = bvec- > bv_len;} out: bio_endio (bio, err); return 0;} static int alloc_ramdev (void) {int i; for (I = 0; I
< RAMHD_MAX_DEVICE; i++){ rdev[i] = kzalloc(sizeof(RAMHD_DEV), GFP_KERNEL); if(!rdev[i]){ return -ENOMEM; } } return 0; } static void clean_ramdev(void) { int i; for(i = 0; i < RAMHD_MAX_DEVICE; i++){ if(rdev[i]) kfree(rdev[i]); } } static int __init ramhd_init(void) { int i; ramhd_space_init(); alloc_ramdev(); ramhd_major = register_blkdev(0, RAMHD_NAME); for(i = 0; i < RAMHD_MAX_DEVICE; i++){ rdev[i]->Data = sdisk [I]; rdev [I]-> queue = blk_alloc_queue (GFP_KERNEL); blk_queue_make_request (queue [I]-> queue, ramhd_make_request); rdev [I]-> gd = alloc_disk (RAMHD_MAX_PARTITIONS); rdev [I]-> gd- > major = ramhd_major; rdev [I]-> gd- > first_minor = I * RAMHD_MAX_PARTITIONS; rdev [I]-> gd- > fops = & ramhd_fops Rdev [I]-> gd- > queue = rdev [I]-> queue; rdev [I]-> gd- > private_data = rdev [I]; sprintf (rdev [I]-> gd- > disk_name, "ramhd%c",'a' + I); rdev [I]-> gd- > flags | = GENHD_FL_SUPPRESS_PARTITION_INFO; set_capacity (rdevI]-> gd, RAMHD_SECTOR_TOTAL); add_disk (rdevI-> gd);} return 0 } static void _ exit ramhd_exit (void) {int i; for (I = 0; I)
< RAMHD_MAX_DEVICE; i++){ del_gendisk(rdev[i]->Gd); put_disk (rdevi-> gd); blk_cleanup_queue (rdevi-> queue);} clean_ramdev (); ramhd_space_clean (); unregister_blkdev (ramhd_major, RAMHD_NAME);} module_init (ramhd_init); module_exit (ramhd_exit); MODULE_AUTHOR ("dennis__chen@ AMDLinuxFGL"); MODULE_DESCRIPTION ("The ramdisk implementation with request function"); MODULE_LICENSE ("GPL")
For everyone's convenience, by the way, let Makefile out. Friends who have seen the previous blog know that this is actually very simple.
Ifneq ($(KERNELRELEASE),) obj-m: = ramdisk.o else PWD: = $(shell pwd) KVER: = $(shell uname-r) KDIR: = / lib/modules/$ (KVER) / build all: $(MAKE)-C $(KDIR) build all $(PWD) modules clean: rm-rf. * .cmd * .o * .mod.c * .ko .tmp _ versions modules.* Module.* endif
Is this code useful or not? You can follow these steps
A) make to generate ramdisk.ko
B) once compiled, you can install the driver, which is done under linux, sudo insmod ramdisk.ko
C) once installed, using ls / dev/ramhd*, you will find two new nodes under / dev, namely / dev/ramhda and / dev/ramhdb
D) you might as well select one of the nodes for partition processing, sudo fdisk / dev/ramhda, and simply create a partition to generate / dev/ramhda1
E) create a file system, sudo mkfs.ext3 / dev/ramhda1
F) with the above file system, you can do mount processing, such as sudo mount / dev/ramhda1 / mnt
G) once the above is done, you can try the copy and delete files, isn't it very simple?
This is the end of the article on "sample Analysis of Block device driver Code in Linux". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, please share it for more people to see.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.