這篇文章將為大家詳細(xì)講解有關(guān)Linux中塊設(shè)備驅(qū)動(dòng)代碼編寫的示例分析,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
為了將block和fs分開,kernel的設(shè)計(jì)者定義了request queue這一種形式。換一句話說,所有fs對(duì)block設(shè)備的請(qǐng)求,最終都會(huì)轉(zhuǎn)變?yōu)閞equest的形式。所以,對(duì)于block設(shè)備驅(qū)動(dòng)開發(fā)的朋友來說,處理好了request queue就掌握了block設(shè)備的一半。當(dāng)然,block設(shè)備很多,hd、floppy、ram都可以這么來定義,有興趣的朋友可以在drivers/block尋找相關(guān)的代碼來閱讀。興趣沒有那么強(qiáng)的同學(xué),可以看看我們這篇博文,基本上也能學(xué)個(gè)大概。有個(gè)基本的概念,再加上一個(gè)簡(jiǎn)單淺顯的范例,對(duì)于一般的朋友來說,已經(jīng)足夠了。
閑話不多說,我們看看一個(gè)ramdisk代碼驅(qū)動(dòng)是怎么寫的,代碼來自《深入linux 設(shè)備驅(qū)動(dòng)程序內(nèi)核機(jī)制》,
#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/types.h> #include <linux/fcntl.h> #include <linux/vmalloc.h> #include <linux/blkdev.h> #include <linux/hdreg.h> #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* rdev[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(rdev[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(rdev[i]->gd, RAMHD_SECTOR_TOTAL); add_disk(rdev[i]->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(rdev[i]->gd); blk_cleanup_queue(rdev[i]->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");
為了大家方便,順便也把Makefile放出來,看過前面blog的朋友都知道,這其實(shí)很簡(jiǎn)單,
ifneq ($(KERNELRELEASE),) obj-m := ramdisk.o else PWD := $(shell pwd) KVER := $(shell uname -r) KDIR := /lib/modules/$(KVER)/build all: $(MAKE) -C $(KDIR) M=$(PWD) modules clean: rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions modules.* Module.* endif
這段代碼究竟有沒有用呢?可以按照下面的步驟來做,
a)make 一下,生成ramdisk.ko;
b)編譯好了之后,就可以安裝驅(qū)動(dòng)了,在linux下是這么做的,sudo insmod ramdisk.ko;
c)安裝好了,利用ls /dev/ramhd*, 就會(huì)發(fā)現(xiàn)在/dev下新增兩個(gè)結(jié)點(diǎn),即/dev/ramhda和/dev/ramhdb;
d)不妨選擇其中一個(gè)節(jié)點(diǎn)進(jìn)行分區(qū)處理, sudo fdisk /dev/ramhda,簡(jiǎn)單處理的話就建立一個(gè)分區(qū), 生成/dev/ramhda1;
e)創(chuàng)建文件系統(tǒng),sudo mkfs.ext3 /dev/ramhda1;
f)有了上面的文件系統(tǒng),就可以進(jìn)行mount處理,不妨sudo mount /dev/ramhda1 /mnt;
g)上面都弄好了,大家就可以copy、delete文件試試了,是不是很簡(jiǎn)單。
關(guān)于“Linux中塊設(shè)備驅(qū)動(dòng)代碼編寫的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。
當(dāng)前題目:Linux中塊設(shè)備驅(qū)動(dòng)代碼編寫的示例分析-創(chuàng)新互聯(lián)
本文URL:http://aaarwkj.com/article46/johhg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供做網(wǎng)站、關(guān)鍵詞優(yōu)化、ChatGPT、標(biāo)簽優(yōu)化、建站公司、Google
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容