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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

转载:谢谢原作者:块设备驱动实战基础篇四 (逐渐成型,加入ioctl通信机制)

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

1.6介紹一種內核與用戶空間通信的方法-misc設備ioctl機制

塊設備驅動開發中往往需要配合用戶態的管理程序工具,管理我們的塊設備,此時我們需要涉及用戶空間程序與塊設備通信的方法,ioctl機制就是接下來需要學習和實戰的,通過ioctl機制,用戶態負責發送各種命令給內核驅動;內核態接收用戶態發送的命令,并根據命令執行相應的動作,如下圖所示。

?

ioctl提供用戶態程序使用內核態函數的通道,此時需要注冊一個字符設備來實現,我們使用misc這個字符設備來實現。

?

Ioctl.h

? 1 #ifndef _IOCTL_H

? 2 #define _IOCTL_H

? 3

? 4 /* misc device name*/

? 5 #define MISC_NAME "ioctl_test"

? 6

? 7 /**

? 8? *define ioctl codes for interfacing between kernel_module and user program

? 9? */

?10 #define IOCTL_CODE????? 0xcc?/* major type code - adjusted for target system */

?11

?12 #define TEST_CMD??????? _IOWR (IOCTL_CODE,? 0x09, unsigned long)

?13

?14 #endif

user.c

?

? 1 #include <sys/ioctl.h>

? 2 #include <unistd.h>

? 3 #include <fcntl.h>

? 4 #include <stdio.h>

? 5 #include "ioctl.h"

? 6

? 7 int main(void)

? 8 {

? 9????????unsigned long arg = 2013;

?10????????int fd;

?11

?12????????fd = open("/dev/"MISC_NAME, O_RDWR, 0);

?13????????if (fd < 0) {

?14???????????????? printf("Failed to open/dev/%s\n", MISC_NAME);

?15???????????????? goto out;

?16????????}

?17

?18????????if (ioctl(fd, TEST_CMD, &arg) < 0) {

?19???????????????? printf("Failed to executeioctl!\n");

?20????????}

?21

?22????????close(fd);

?23 out:

?24????????return 0;

?25 }

kernel.c

? 1 /*

? 2? * IOCTL

? 3? *Author: talk@studio

? 4? */

? 5

? 6 #include <linux/fs.h>

? 7 #include <linux/uaccess.h>

? 8 #include <linux/module.h>

? 9 #include <linux/miscdevice.h>

?10

?11 #include "ioctl.h"

?12

?13 static int ioctl(struct inode *inode,struct file *file,

?14????????????????????? unsigned int cmd,unsigned long user)

?15 {

?16????????unsigned long arg;

?17????????int ret = 0;

?18

?19????????if (_IOC_TYPE(cmd) != IOCTL_CODE) {

?20???????????????? printk("Unknown ioctlcommand 0x%x\n", cmd);

?21???? ????????????ret = -ENOTTY;

?22???????????????? goto out;

?23????????}

?24

?25????????switch (cmd) {

?26???????????????? case TEST_CMD:

?27???????????????????????? ret =copy_from_user(&arg, (unsigned long *)user, sizeof(unsigned lon??? g));

?28????????????????????????if (ret) {

?29????????????????????????????????printk("copy from user failed!\n");

?30???????????????????????? } else {

?31????????????????????????????????printk("received IOctl[arg=%lu] from user!\n", arg);

?32???????????????????????? }

?33???????????????????????? break;

?34???????????????? default:

?35???????????????????????? printk("Unknownioctl command[0x%x].\n", cmd);

36???????????????????????? ret = -ENOTTY;

?37???????????????????????? break;

?38????????}

?39 out:

?40????????return ret;

?41 }

?42

?43 static struct file_operations_misc_ctl_fops = {

?44????????.ioctl = ioctl,

?45????????.owner = THIS_MODULE,

?46 };

?47

?48 static struct miscdevice _misc_dev = {

?49????????.minor = MISC_DYNAMIC_MINOR,

?50????????.name = MISC_NAME,

?51????????.fops = &_misc_ctl_fops

?52 };

?53

?54 static int __init ioctl_init(void)

?55 {

?56????????int ret;

?57

?58????????ret = misc_register(&_misc_dev);

?59????????if (ret) {

?60???????????????? printk("Register ioctldevice[%s] failed\n", _misc_dev.name);

?61????????}

?62????????return ret;

?63 }

?64

?65 static void __exit ioctl_exit(void)

?66 {

?67????????if (misc_deregister(&_misc_dev) < 0) {

?68???????????????? printk("Deregister ioctlcontrol device[%s] failed\n",?_misc_dev.name);

?69????????}

?70????????return;

71 }

?72

?73 module_init(ioctl_init);

?74 module_exit(ioctl_exit);

?75 MODULE_LICENSE("GPL");

1.7逐漸成型 - 構件完善的管理工具及內核塊設備驅動模塊

經過上面四節的實戰和學習,我們把代碼完善一下,實現一個完整的用戶態管理功能和內核塊設備驅動的代碼設計,我們需要完成如下功能,下圖展示了我們程序各個模塊的關系。

?

?

我們看一下代碼如何實現,首先看公用頭文件定義

fbd_ioctl.h

?

? 1 /*

? 2? *Author: talk@studio

? 3? */

? 4

? 5 #ifndef _IOCTL_H

? 6 #define _IOCTL_H

? 7

? 8 /* misc device name*/

? 9 #define MISC_NAME "fbd_misc_dev"

?10

?11 /* param structure for device create */

?12 struct create_param {

?13????????char fbd_dev_name[32];

?14????????char lower_dev_path[64];

?15 };

?16

?17 struct delete_param {

?18????????char fbd_dev_name[32];

?19 };

?20

?21 /**

?22? *define ioctl codes for interfacing between kernel_module and user program

?23? */

?24 #define IOCTL_CODE????? 0xcc?/* major type code - adjusted for target system */

?25

?26 #define CREATE_CMD????? _IOWR (IOCTL_CODE,? 0x0A, struct create_param)

?27 #define DELETE_CMD????? _IOWR (IOCTL_CODE,? 0x0B, struct delete_param)

?28

?29 #endif

?

?

?

用戶態代碼

?

? 1 /*

? 2? *Author: talk@studio

? 3? */

? 4

? 5 #include <sys/ioctl.h>

? 6 #include <unistd.h>

? 7 #include <fcntl.h>

? 8 #include <stdio.h>

? 9

?10 #include"../common/include/fbd_ioctl.h"

?11

?12 int main(void)

?13 {

?14????????int fd;

?15????????struct create_param ctr_param = {

?16???????????????? .fbd_dev_name ="fbd_dev1",

?17???????????????? .lower_dev_path = "/dev/sdb",

?18????????};

?19

?20????????fd = open("/dev/"MISC_NAME, O_RDWR, 0);

?21????????if (fd < 0) {

?22???????????????? printf("Failed to open/dev/%s\n", MISC_NAME);

?23???????????????? goto out;

?24????????}

?25

?26????????if (ioctl(fd, CREATE_CMD, &ctr_param) < 0) {

?27???????????????? printf("Failed to executeioctl!\n");

?28????????}

?29

?30????????close(fd);

?31 out:

?32????????return 0;

?33 }

?34

? 1 /*

? 2? *Author: talk@studio

? 3? */

? 4

? 5 #include <sys/ioctl.h>

? 6 #include <unistd.h>

? 7 #include <fcntl.h>

? 8 #include <stdio.h>

? 9

?10 #include"../common/include/fbd_ioctl.h"

?11

?12 int main(void)

?13 {

?14????????int fd;

?15????????struct delete_param del_param = {

?16???????????????? .fbd_dev_name ="fbd_dev1",

?17????????};

?18

?19????????fd = open("/dev/"MISC_NAME, O_RDWR, 0);

?20????????if (fd < 0) {

?21???????????????? printf("Failed to open/dev/%s\n", MISC_NAME);

?22???????????????? goto out;

?23????????}

?24

?25????????if (ioctl(fd, DELETE_CMD, &del_param) < 0) {

?26???????????????? printf("Failed to executeioctl!\n");

?27????????}

?28

?29????????close(fd);

?30 out:

?31????????return 0;

?32 }

?33

?

?

內核驅動代碼

?

? 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 #include <linux/fs.h>

? 9 #include <linux/uaccess.h>

?10 #include <linux/miscdevice.h>

?11

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

?13 #define DEV_NAME_LEN??????????? 32

?14

?15 #define DRIVER_NAME???????????? "filter driver"

?16

?17 struct fbd_dev {

?18????????char fbd_dev_name[DEV_NAME_LEN];

?19????????struct request_queue *queue;

?20????????struct gendisk *disk;

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

?22

?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 #include "../common/include/fbd_ioctl.h"

? 7

? 8 static int fbd_driver_major = 0;

? 9

?10 static struct fbd_dev fbd_dev =

?11 {

?12????????.fbd_dev_name = "\0",

?13????????.queue = NULL,

?14????????.disk = NULL,

?15????????.lower_dev_name = "\0",

?16????????.lower_bdev = NULL,

?17??? ?????.size = 0

?18 };

?19

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

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

?22

?23 static struct block_device_operationsdisk_fops = {

?24????????.open = fbddev_open,

?25????????.release = fbddev_close,

?26????????.owner = THIS_MODULE,

?27 };

?28

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

?30 {

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

?32????????return 0;

?33 }

?34

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

?36 {

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

?38????????return 0;

?39 }

?40

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

?42 {

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

?44

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

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

?47????????kfree(ctx);

?48

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

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

?51???????????????? bio->bi_sector);

?52

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

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

?55????????}

?56

?57????????return 0;

?58 }

?59

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

?61 {

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

?63????????struct bio_context *ctx;

?64

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

?66????????????????"access on devsector [%llu], length is [%u] sectors.\n",

?67???????????????? dev->disk->disk_name,

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

?69???????????????? bio->bi_sector,

?70???????????????? bio_sectors(bio));

?71

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

73???????? if (!ctx) {

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

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

?76???????????????? goto out;

?77??? ?????}

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

?79

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

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

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

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

?84

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

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

?87 out:

?88????????return 0;

?89 }

?90

?91 static int dev_create(char *fbd_dev_name,char *lower_dev_path)

?92 {

?93????????int ret = 0;

?94????????struct fbd_dev *dev = &fbd_dev;

?95

?96????????if(fbd_dev.disk){

?97???????????????? printk("device[%s] isalready exist, delete it first!\n", fbd_dev.fbd_dev_nam??? e);

?98???????????????? ret = -EEXIST;

?99???????????????? return ret;

100???????? }

101

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

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

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

105???????????????? ret = -ENOMEM;

106???????????????? goto err_out1;

107???????? }

108

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

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

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

112???????????????? ret = -ENOMEM;

113???????????????? goto err_out2;

114???????? }

115

116???????? /* init queue */

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

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

119

120???????? /* init gendisk */

121???????? strncpy(dev->disk->disk_name,fbd_dev_name, DEV_NAME_LEN);

122???????? dev->disk->major =fbd_driver_major;

123???????? dev->disk->first_minor = 0;

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

125

126???????? dev->lower_bdev =open_bdev_excl(lower_dev_path, FMODE_WRITE | FMODE_READ, dev->lower??? _bdev);

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

128???????????????? printk("Open thedevice[%s]'s lower dev [%s] failed!\n", fbd_dev_name, lower_??? dev_path);

129???????????????? ret = -ENOENT;

130???????????????? goto err_out3;

131???????? }

132

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

134

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

136

137???????? /* bind queue to disk */

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

139

140???????? /* add disk to kernel */

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

142

143???????? strncpy(dev->fbd_dev_name,fbd_dev_name, DEV_NAME_LEN);

144???????? strncpy(dev->lower_dev_name,lower_dev_path, DEV_NAME_LEN);

145???????? return 0;

146err_out3:

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

148err_out2:

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

150err_out1:

151???????? memset(&fbd_dev, 0, sizeof(structfbd_dev));

152? ???????return ret;

153 }

154

155 staticint dev_delete(char *fbd_dev_name)

156 {

157???????? int ret = 0;

158???????? struct fbd_dev *dev = &fbd_dev;

159

160???????? if (strcmp(fbd_dev_name,dev->fbd_dev_name) == 0) {

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

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

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

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

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

166???????????????? memset(&fbd_dev, 0,sizeof(struct fbd_dev));

167???????? } else {

168???????????????? printk("device[%s] isn'texist!\n", fbd_dev_name);

169???????????????? ret = -EEXIST;

170???????? }

171???????? return ret;

172 }

173

174 staticint ioctl(struct inode *inode, struct file *file,

175????????????????????? unsigned int cmd,unsigned long user)

176 {

177???????? struct delete_param del_param;

178???????? struct create_param ctr_param;

179???????? int ret = 0;

180

181???????? if (_IOC_TYPE(cmd) != IOCTL_CODE) {

182???? ????????????printk("Unknown ioctl command0x%x\n", cmd);

183???????????????? ret = -ENOTTY;

184???????????????? goto out;

185???????? }

186

187???????? switch (cmd) {

188???????????????? case CREATE_CMD:

189???????????????????????? ret =copy_from_user(&ctr_param, (void *)user, sizeof(struct create_p??? aram));

190???????????????????????? if (ret) {

191????????????????????????????????printk("copy from user failed!\n");

192???????????????????????? } else {

193???????????????????????????????? ret = dev_create(ctr_param.fbd_dev_name,ctr_param.lower_dev_??? path);

194???????????????????????? }

195???????????????????????? break;

196???????????????? case DELETE_CMD:

197???????????????????????? ret =copy_from_user(&del_param, (void *)user, sizeof(struct delete_p??? aram));

198???????????????????????? if (ret) {

199????????????????????????????????printk("copy from user failed!\n");

200???????????????????????? } else {

201???????????????????????????????? ret =dev_delete(del_param.fbd_dev_name);

202????????????? ???????????}

203???????????????????????? break;

204???????????????? default:

205???????????????????????? printk("Unknownioctl command[0x%x].\n", cmd);

206???????????????????????? ret = -ENOTTY;

207???????????????????????? break;

208???????? }

209 out:

210???????? return ret;

211 }

212

213 staticstruct file_operations _misc_ctl_fops = {

214???????? .ioctl = ioctl,

215???????? .owner = THIS_MODULE,

216 };

217

218 staticstruct miscdevice _misc_dev = {

219???????? .minor = MISC_DYNAMIC_MINOR,

220???????? .name = MISC_NAME,

221???????? .fops = &_misc_ctl_fops

222 };

223

224 staticint __init fbd_driver_init(void)

225 {

226???????? int ret;

227

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

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

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

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

232???????????????? ret = -EIO;

233???????????????? goto err_out1;

234???????? }

235

236???????? ret = misc_register(&_misc_dev);

237???? ????if (ret) {

238???????????????? printk("Register ioctldevice[%s] failed\n", _misc_dev.name);

239???????????????? goto err_out2;

240???????? }

241

242???????? printk("block device driver initsuccessfuly!\n");

243???????? return ret;

244err_out2:

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

246err_out1:

247???????? return ret;

248 }

249

250 staticvoid __exit fbd_driver_exit(void)

251 {

252???????? if(fbd_dev.disk){

253???????????????? printk("device[%s] isalready exist, delete it first!\n", fbd_dev.fbd_dev_nam??? e);

254????????????????dev_delete(fbd_dev.fbd_dev_name);

255???????? }

256

257???????? if(misc_deregister(&_misc_dev)< 0) {

258???????????????? printk("Deregister ioctlcontrol device[%s] failed\n",?_misc_dev.name);

259???????? }

260

261???????? /* unregister fbd driver */

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

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

264 }

265

266module_init(fbd_driver_init);

267module_exit(fbd_driver_exit);

268MODULE_LICENSE("GPL");

總結

以上是生活随笔為你收集整理的转载:谢谢原作者:块设备驱动实战基础篇四 (逐渐成型,加入ioctl通信机制)的全部內容,希望文章能夠幫你解決所遇到的問題。

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