日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

转载:谢谢原作者:块设备驱动实战基础篇三 (BIO请求回调机制)

發布時間:2025/3/21 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 转载:谢谢原作者:块设备驱动实战基础篇三 (BIO请求回调机制) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.5 塊設備請求返回處理回調機制

?

本節我們繼續完善1.4節中的代碼,在上節我們完成了請求的過濾轉發,那么請求被磁盤處理完成后返回回來的路徑處理是怎樣的,本節我們繼續帶著這樣的問題再一次完善我們的驅動程序,通過本節的學習,我們能夠真正掌握請求處理,轉發過濾,請求完成后回調處理機制的完整學習。

?

先給出完善后的IO架構圖,我們對比一下1.4節最后給出的圖有何區別:

?

相比1.4節,在fbd_driver框圖右側增加了fbd_driver end io function處理模塊,底層設備sd#的請求返回后,進入fbd_driver的請求回調處理函數中。我們再次貼一下完善后的代碼。

?

? 1 #ifndef?_FBD_DRIVER_H

? 2 #define?_FBD_DRIVER_H

? 3 #include <linux/init.h>

? 4 #include <linux/module.h>

? 5 #include <linux/blkdev.h>

? 6 #include <linux/bio.h>

? 7 #include <linux/genhd.h>

? 8

? 9 #define SECTOR_BITS???????????? (9)

?10 #define DEV_NAME_LEN??? ????????32

?11

?12 #define DRIVER_NAME???????????? "filter driver"

?13

?14 #define DEVICE1_NAME??????????? "fbd1_dev"

?15 #define DEVICE1_MINOR?????????? 0

?16 #define DEVICE2_NAME??????????? "fbd2_dev"

?17 #define DEVICE2_MINOR?????????? 1

?18

?19 struct fbd_dev {

?20????????struct request_queue *queue;

?21????????struct gendisk *disk;

?22????????sector_t size;????????? /* devicesize in Bytes */

?23????????char lower_dev_name[DEV_NAME_LEN];

?24????????struct block_device *lower_bdev;

?25 };

?26

?27 struct bio_context {

?28????????void *old_private;

?29????????void *old_callback;

?30 };

?31 #endif

?

? 1 /**

? 2?*? fbd-driver - filter blockdevice driver

? 3?*? Author: Talk@studio

? 4 **/

? 5 #include "fbd_driver.h"

? 6

? 7 static int fbd_driver_major = 0;

? 8

? 9 static struct fbd_dev fbd_dev1 =

?10 {

?11????????.queue = NULL,

?12????????.disk = NULL,

?13????????.lower_dev_name = "/dev/sdb",

?14????????.lower_bdev = NULL,

?15????????.size = 0

?16 };

?17

?18 static struct fbd_dev fbd_dev2 =

?19 {

?20????????.queue = NULL,

?21????????.disk = NULL,

?22????????.lower_dev_name = "/dev/sdc",

?23????????.lower_bdev = NULL,

?24????????.size = 0

?25 };

?26

?27 static int fbddev_open(struct inode *inode,struct file *file);

?28 static int fbddev_close(struct inode*inode, struct file *file);

?29

?30 static struct block_device_operationsdisk_fops = {

?31????????.open = fbddev_open,

?32????????.release = fbddev_close,

?33????????.owner = THIS_MODULE,

?34 };

?35

?36 static int fbddev_open(struct inode *inode,struct file *file)

37 {

?38????????printk("device is opened by:[%s]\n", current->comm);

?39????????return 0;

?40 }

?41

?42 static int fbddev_close(struct inode*inode, struct file *file)

?43 {

?44????????printk("device is closed by:[%s]\n", current->comm);

?45????????return 0;

?46 }

?47

?48 static int fbd_io_callback(struct bio *bio,unsigned int bytes_done, int error)

?49 {

?50????????struct bio_context *ctx = bio->bi_private;

?51

?52????????bio->bi_private = ctx->old_private;

?53????????bio->bi_end_io = ctx->old_callback;

?54????????kfree(ctx);

?55

?56????????printk("returned [%s] io request, end on sector %llu!\n",

?57???????????????? bio_data_dir(bio) == READ ?"read" : "write",

?58???????????????? bio->bi_sector);

?59

?60????????if (bio->bi_end_io) {

?61???????????????? bio->bi_end_io(bio,bytes_done, error);

?62????????}

?63

?64????????return 0;

?65 }

?66

?67 static int make_request(structrequest_queue *q, struct bio *bio)

?68 {

?69????????struct fbd_dev *dev = (struct fbd_dev *)q->queuedata;

?70????????struct bio_context *ctx;

?71

?72????????printk("device [%s] recevied [%s] io request, "

73???????????????? "access on dev sector[%llu], length is [%u] sectors.\n",

?74???????????????? dev->disk->disk_name,

?75 ????????????????bio_data_dir(bio) == READ ?"read" : "write",

?76???????????????? bio->bi_sector,

?77???????????????? bio_sectors(bio));

?78

?79????????ctx = kmalloc(sizeof(struct bio_context), GFP_KERNEL);

?80????????if (!ctx) {

?81???????????????? printk("alloc memory forbio_context failed!\n");

?82???????????????? bio_endio(bio,bio->bi_size, -ENOMEM);

?83???????????????? goto out;

?84????????}

?85????????memset(ctx, 0, sizeof(struct bio_context));

?86

?87????????ctx->old_private = bio->bi_private;

?88????????ctx->old_callback = bio->bi_end_io;

?89????????bio->bi_private = ctx;

?90????????bio->bi_end_io = fbd_io_callback;

?91

?92????????bio->bi_bdev = dev->lower_bdev;

?93????????submit_bio(bio_rw(bio), bio);

?94 out:

?95????????return 0;

?96 }

?97

?98 static int dev_create(struct fbd_dev *dev,char *dev_name, int major, int minor)

?99 {

100???????? int ret = 0;

101

102???????? /* init fbd_dev */

103???????? dev->disk = alloc_disk(1);

104???????? if (!dev->disk) {

105???????????????? printk("alloc diskerror");

106???????????????? ret = -ENOMEM;

107???????????????? goto err_out1;

108???????? }

109

110???????? dev->queue =blk_alloc_queue(GFP_KERNEL);

111???????? if (!dev->queue) {

112???????????????? printk("alloc queueerror");

113??????? ?????????ret = -ENOMEM;

114???????????????? goto err_out2;

115???????? }

116

117???????? /* init queue */

118???????? blk_queue_make_request(dev->queue,make_request);

119???????? dev->queue->queuedata = dev;

120

121???????? /* init gendisk */

122?????? ??strncpy(dev->disk->disk_name, dev_name,DEV_NAME_LEN);

123???????? dev->disk->major = major;

124???????? dev->disk->first_minor = minor;

125???????? dev->disk->fops =&disk_fops;

126

127???????? dev->lower_bdev =open_bdev_excl(dev->lower_dev_name, FMODE_WRITE | FMODE_READ,dev->lower_bdev);

128???????? if (IS_ERR(dev->lower_bdev)) {

129???????????????? printk("Open thedevice[%s]'s lower dev [%s] failed!\n", dev_name, dev->lower_dev_name);

130???????????????? ret = -ENOENT;

131???????????????? goto err_out3;

132???????? }

133

134???????? dev->size =get_capacity(dev->lower_bdev->bd_disk) << SECTOR_BITS;

135

136???????? set_capacity(dev->disk,(dev->size >> SECTOR_BITS));

137

138???????? /* bind queue to disk */

139???????? dev->disk->queue = dev->queue;

140

141???????? /* add disk to kernel */

142???????? add_disk(dev->disk);

143???????? return 0;

144err_out3:

145???????? blk_cleanup_queue(dev->queue);

146err_out2:

147???????? put_disk(dev->disk);

148err_out1:

149???????? return ret;

150 }

151

152 staticvoid dev_delete(struct fbd_dev *dev, char *name)

153 {

154???????? printk("delete the device[%s]!\n", name);

155???????? close_bdev_excl(dev->lower_bdev);

156

157???????? blk_cleanup_queue(dev->queue);

158???????? del_gendisk(dev->disk);

159???? ????put_disk(dev->disk);

160 }

161

162 staticint __init fbd_driver_init(void)

163 {

164???????? int ret;

165

166???????? /* register fbd driver, get the drivermajor number*/

167???????? fbd_driver_major =register_blkdev(fbd_driver_major, DRIVER_NAME);

168???????? if (fbd_driver_major < 0) {

169???????????????? printk("get majorfail");

170???????????????? ret = -EIO;

171???????????????? goto err_out1;

172???????? }

173

174???????? /* create the first device */

175???????? ret = dev_create(&fbd_dev1, DEVICE1_NAME,fbd_driver_major, DEVICE1_MINOR);

176???????? if (ret) {

177???????????????? printk("create device[%s] failed!\n", DEVICE1_NAME);

178???????????????? goto err_out2;

179???????? }

180

181???????? /* create the second device */

182???????? ret = dev_create(&fbd_dev2,DEVICE2_NAME, fbd_driver_major, DEVICE2_MINOR);

183???????? if (ret) {

184???????????????? printk("create device[%s] failed!\n", DEVICE2_NAME);

185???????????????? goto err_out3;

186???????? }

187???????? return ret;

188err_out3:

189???????? dev_delete(&fbd_dev1,DEVICE1_NAME);

190err_out2:

191???????? unregister_blkdev(fbd_driver_major,DRIVER_NAME);

192err_out1:

193???????? return ret;

194 }

195

196 staticvoid __exit fbd_driver_exit(void)

197 {

198???????? /* delete the two devices */

199???????? dev_delete(&fbd_dev2,DEVICE2_NAME);

200???????? dev_delete(&fbd_dev1,DEVICE1_NAME);

201

202???????? /* unregister fbd driver */

203???????? unregister_blkdev(fbd_driver_major,DRIVER_NAME);

204???????? printk("block device driver exitsuccessfuly!\n");

205 }

206

207module_init(fbd_driver_init);

208module_exit(fbd_driver_exit);

209MODULE_LICENSE("GPL");

?

先看頭文件的變化,27-30行我們新定義了一個數據結構bio_context,顧名思義該數據結構用于描述bio請求的上下文信息,里面有兩個成員,都是指針,old_private指針用于保存bio中private指針內容,old_callback用于保存bio中舊的回調函數指針。

?

接下來分析fbd_driver.c,我們直接看make_request函數,67-96行。

?

67 staticint make_request(struct request_queue *q, struct bio *bio)

?68 {

?69????????struct fbd_dev *dev = (struct fbd_dev *)q->queuedata;

?70????????struct bio_context *ctx;

?71

?72????????printk("device [%s] recevied [%s] io request, "

?73???????????????? "access on dev sector[%llu], length is [%u] sectors.\n",

?74???????????????? dev->disk->disk_name,

?75???????????????? bio_data_dir(bio) == READ ?"read" : "write",

?76???????????????? bio->bi_sector,

?77???????????????? bio_sectors(bio));

?78

?79????????ctx = kmalloc(sizeof(struct bio_context), GFP_KERNEL);

?80 ????????if (!ctx) {

?81???????????????? printk("alloc memory forbio_context failed!\n");

?82???????????????? bio_endio(bio,bio->bi_size, -ENOMEM);

?83???????????????? goto out;

?84????????}

?85????????memset(ctx, 0, sizeof(struct bio_context));

?86

?87????????ctx->old_private = bio->bi_private;

?88????????ctx->old_callback = bio->bi_end_io;

?89????????bio->bi_private = ctx;

?90????????bio->bi_end_io = fbd_io_callback;

?91

?92????????bio->bi_bdev = dev->lower_bdev;

?93????????submit_bio(bio_rw(bio), bio);

?94 out:

?95????????return 0;

?96 }

?

?

70行定義了一個bio_context指針變量,79行通過kmalloc函數為ctx指針申請了內存并賦值,這樣我們申請bio的上下文信息數據結構,并在85行用memset函數將ctx數據結構清空,接下來87-88行,我們保存了bio中的bi_private指針和bi_end_io回調函數指針,在90-91行把bio中的這兩個指針重新賦值了,bi_private賦值為ctx指針值,bi_end_io回調函數指針賦值為fbd_io_callback函數指針,這樣我們完成了bio請求的再次加工處理,我們趁熱打鐵繼續分析fbd_io_callback函數一探究竟,搞清楚這么的做的原因。

?

?48 static int fbd_io_callback(struct bio *bio,unsigned int bytes_done, int error)

?49 {

?50????????struct bio_context *ctx = bio->bi_private;

?51

?52????????bio->bi_private = ctx->old_private;

?53????????bio->bi_end_io = ctx->old_callback;

?54????????kfree(ctx);

?55

?56????????printk("returned [%s] io request, end on sector %llu!\n",

?57???????????????? bio_data_dir(bio) == READ ?"read" : "write",

?58??? ?????????????bio->bi_sector);

?59

?60????????if (bio->bi_end_io) {

?61???????????????? bio->bi_end_io(bio,bytes_done, error);

?62????????}

?63

?64????????return 0;

?65 }

?

輸入參數是bio指針以及請求完成的子結束和錯誤標志,由于在90行我們把bio中bi_private的指針賦值到ctx指針中,這樣50行的代碼我們就可以重新獲取ctx指針,進而52-53行我們重新恢復bio的bi_private/bi_end_io指針值,最后54行釋放ctx,因為此時ctx中的指針值我們已恢復,ctx已不再有用可以釋放其占用的內存,我們繼續調用bio原本就注冊好的bi_end_io回調函數,完成真正的請求處理結束操作。

?

?????? 至此,我們走完了完整的請求處理,轉發過濾,完成回調全過程。

P.S.: 注意此篇并沒有深入剖析硬中斷->軟中斷->bio回調處理過程,我們先知道請求會通過我們注冊的回調函數返回即可,后續再深入剖析操作系統細節。

總結

以上是生活随笔為你收集整理的转载:谢谢原作者:块设备驱动实战基础篇三 (BIO请求回调机制)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。