转载:谢谢原作者:块设备驱动实战基础篇四 (逐渐成型,加入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逐渐成型 - 构件完善的管理工具及内核块设备驱动模块
经过上面四节的实战和学习,我们把代码完善一下,实现一个完整的用户态管理功能和内核块设备驱动的代码设计,我们需要完成如下功能,下图展示了我们程序各个模块的关系。
9 #define MISC_NAME "fbd_misc_dev"
11 /* param structure for device create */
22 *define ioctl codes for interfacing between kernel_module and user program
24 #define IOCTL_CODE 0xcc /* major type code - adjusted for target system */
26 #define CREATE_CMD _IOWR (IOCTL_CODE, 0x0A, struct create_param)
27 #define DELETE_CMD _IOWR (IOCTL_CODE, 0x0B, struct delete_param)
10 #include"../common/include/fbd_ioctl.h"
15 struct create_param ctr_param = {
17 .lower_dev_path = "/dev/sdb",
20 fd = open("/dev/"MISC_NAME, O_RDWR, 0);
22 printf("Failed to open/dev/%s\n", MISC_NAME);
26 if (ioctl(fd, CREATE_CMD, &ctr_param) < 0) {
27 printf("Failed to executeioctl!\n");
10 #include"../common/include/fbd_ioctl.h"
15 struct delete_param del_param = {
19 fd = open("/dev/"MISC_NAME, O_RDWR, 0);
21 printf("Failed to open/dev/%s\n", MISC_NAME);
25 if (ioctl(fd, DELETE_CMD, &del_param) < 0) {
26 printf("Failed to executeioctl!\n");
10 #include <linux/miscdevice.h>
15 #define DRIVER_NAME "filter driver"
18 char fbd_dev_name[DEV_NAME_LEN];
19 struct request_queue *queue;
21 sector_t size; /* devicesize in Bytes */
23 char lower_dev_name[DEV_NAME_LEN];
24 struct block_device *lower_bdev;
2 * fbd-driver - filter blockdevice driver
6 #include "../common/include/fbd_ioctl.h"
8 static int fbd_driver_major = 0;
10 static struct fbd_dev fbd_dev =
20 static int fbddev_open(struct inode *inode,struct file *file);
21 static int fbddev_close(struct inode*inode, struct file *file);
23 static struct block_device_operationsdisk_fops = {
29 static int fbddev_open(struct inode *inode,struct file *file)
31 printk("device is opened by:[%s]\n", current->comm);
35 static int fbddev_close(struct inode*inode, struct file *file)
37 printk("device is closedby:[%s]\n", current->comm);
41 static int fbd_io_callback(struct bio *bio,unsigned int bytes_done, int error)
43 struct bio_context *ctx = bio->bi_private;
45 bio->bi_private = ctx->old_private;
46 bio->bi_end_io = ctx->old_callback;
49 printk("returned [%s] io request, end on sector %llu!\n",
50 bio_data_dir(bio) == READ ?"read" : "write",
54 bio->bi_end_io(bio,bytes_done, error);
60 static int make_request(structrequest_queue *q, struct bio *bio)
62 struct fbd_dev *dev = (struct fbd_dev *)q->queuedata;
65 printk("device [%s] recevied [%s] io request, "
66 "access on devsector [%llu], length is [%u] sectors.\n",
68 bio_data_dir(bio) == READ ?"read" : "write",
72 ctx = kmalloc(sizeof(struct bio_context), GFP_KERNEL);
74 printk("alloc memory forbio_context failed!\n");
75 bio_endio(bio,bio->bi_size, -ENOMEM);
78 memset(ctx, 0, sizeof(struct bio_context));
80 ctx->old_private = bio->bi_private;
81 ctx->old_callback = bio->bi_end_io;
83 bio->bi_end_io = fbd_io_callback;
85 bio->bi_bdev = dev->lower_bdev;
86 submit_bio(bio_rw(bio), bio);
91 static int dev_create(char *fbd_dev_name,char *lower_dev_path)
94 struct fbd_dev *dev = &fbd_dev;
97 printk("device[%s] isalready exist, delete it first!\n", fbd_dev.fbd_dev_nam e);
102 dev->disk = alloc_disk(1);
104 printk("alloc diskerror");
109 dev->queue =blk_alloc_queue(GFP_KERNEL);
111 printk("alloc queueerror");
117 blk_queue_make_request(dev->queue,make_request);
118 dev->queue->queuedata = dev;
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;
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);
133 dev->size =get_capacity(dev->lower_bdev->bd_disk) << SECTOR_BITS;
135 set_capacity(dev->disk,(dev->size >> SECTOR_BITS));
138 dev->disk->queue =dev->queue;
143 strncpy(dev->fbd_dev_name,fbd_dev_name, DEV_NAME_LEN);
144 strncpy(dev->lower_dev_name,lower_dev_path, DEV_NAME_LEN);
147 blk_cleanup_queue(dev->queue);
151 memset(&fbd_dev, 0, sizeof(structfbd_dev));
155 staticint dev_delete(char *fbd_dev_name)
158 struct fbd_dev *dev = &fbd_dev;
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);
165 blk_cleanup_queue(dev->queue);
166 memset(&fbd_dev, 0,sizeof(struct fbd_dev));
168 printk("device[%s] isn'texist!\n", fbd_dev_name);
174 staticint ioctl(struct inode *inode, struct file *file,
175 unsigned int cmd,unsigned long user)
177 struct delete_param del_param;
178 struct create_param ctr_param;
181 if (_IOC_TYPE(cmd) != IOCTL_CODE) {
182 printk("Unknown ioctl command0x%x\n", cmd);
189 ret =copy_from_user(&ctr_param, (void *)user, sizeof(struct create_p aram));
191 printk("copy from user failed!\n");
193 ret = dev_create(ctr_param.fbd_dev_name,ctr_param.lower_dev_ path);
197 ret =copy_from_user(&del_param, (void *)user, sizeof(struct delete_p aram));
199 printk("copy from user failed!\n");
201 ret =dev_delete(del_param.fbd_dev_name);
205 printk("Unknownioctl command[0x%x].\n", cmd);
213 staticstruct file_operations _misc_ctl_fops = {
218 staticstruct miscdevice _misc_dev = {
219 .minor = MISC_DYNAMIC_MINOR,
224 staticint __init fbd_driver_init(void)
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) {
236 ret = misc_register(&_misc_dev);
238 printk("Register ioctldevice[%s] failed\n", _misc_dev.name);
242 printk("block device driver initsuccessfuly!\n");
245 unregister_blkdev(fbd_driver_major,DRIVER_NAME);
250 staticvoid __exit fbd_driver_exit(void)
253 printk("device[%s] isalready exist, delete it first!\n", fbd_dev.fbd_dev_nam e);
254 dev_delete(fbd_dev.fbd_dev_name);
257 if(misc_deregister(&_misc_dev)< 0) {
258 printk("Deregister ioctlcontrol device[%s] failed\n", _misc_dev.name);
261 /* unregister fbd driver */
262 unregister_blkdev(fbd_driver_major,DRIVER_NAME);
263 printk("block device driver exitsuccessfuly!\n");
266module_init(fbd_driver_init);
267module_exit(fbd_driver_exit);
转载:谢谢原作者:块设备驱动实战基础篇四 (逐渐成型,加入ioctl通信机制)相关推荐
- 转载:谢谢原作者: 块设备驱动实战基础篇二 (继续完善170行过滤驱动代码至200行)
1.3块设备驱动关键数据结构及函数API详细剖析 经过上节四个步骤我们已经熟悉并实战了一个最基本的过滤块设备驱动的设计技巧,我们这一节先不继续实战,我们本节把上节170行代码中接触到的块设备核心数据结 ...
- 转载:谢谢原作者:块设备驱动实战基础篇一 (170行代码构建一个逻辑块设备驱动)
1 内核块设备驱动基础学习与实战 1.1 设备驱动IO架构初探 操作系统是如何将数据读到缓冲区的,发生了什么?我们带着这样的问题,粗略走一下read调用系统过程,希望这个初探,可以唤起大家研究操作 ...
- 转载:谢谢原作者:块设备驱动实战基础篇三 (BIO请求回调机制)
1.5 块设备请求返回处理回调机制 本节我们继续完善1.4节中的代码,在上节我们完成了请求的过滤转发,那么请求被磁盘处理完成后返回回来的路径处理是怎样的,本节我们继续带着这样的问题再一次完善我们的驱动 ...
- linux块设备驱动编写,Linux内核学习笔记 -49 工程实践-编写块设备驱动的基础
块设备可以随机存储.字符设备,比如键盘,只能按照输入顺序存取,不可随机,打乱输入的字节流. 文件系统层,包括常见的文件系统,以及虚拟文件系统层VFS,字符设备可以直接用应用程序打开.块设备不会在应用程 ...
- Linux 字符设备驱动开发基础(四)—— ioctl() 函数解析
解析完 open.close.read.write 四个函数后,终于到我们的 ioctl() 函数了 一. 什么是ioctl ioctl是设备驱动程序中对设备的I/O通道进行管理的函数.所谓对I/O通 ...
- 块设备驱动、bio理解
别人写过的内容,我就不写了.贴一下大佬的博客,写的非常好: 块设备驱动实战基础篇一 (170行代码构建一个逻辑块设备驱动) 块设备驱动实战基础篇二 (继续完善170行过滤驱动代码至200行) 块设备驱 ...
- Nginx实战基础篇六 通过源码包编译安装部署LNMP搭建Discuz论坛
Nginx实战基础篇六 通过源码包编译安装部署LNMP搭建Discuz论坛 版权声明: 本文遵循"署名非商业性使用相同方式共享 2.5 中国大陆"协议 您可以自由复制.发行.展览. ...
- Nginx实战基础篇一 源码包编译安装部署web服务器
Nginx实战基础篇一 源码包编译安装部署web服务器 版权声明: 本文遵循"署名非商业性使用相同方式共享 2.5 中国大陆"协议 您可以自由复制.发行.展览.表演.放映.广播或通 ...
- 转:写一个块设备驱动
----------------------- Page 1----------------------- 第 1章 +---------------------------------------- ...
最新文章
- Powercli 批量获取vmhost 时间
- Nginx防盗链与访问控制
- OpenCV3编程入门(毛星云)之视频读取与播放
- gis中dbf转为csv_Python中.dbf到.csv的批量转换
- 工具 - MyEclipse算法机最新8.6forSpring有效
- 转wordpress小工具制作前台后台全解析
- 【渝粤教育】21秋期末考试马克思主义基本原理概论(A)10882k1 (2)
- python 裁判文书网_python - 用selenium模拟登陆裁判文书网,系统报错找不到元素。...
- vscode浏览器扩展(图文教程) - 设置篇
- 枚举算法:求两个整数m,n(m>n)最大公约数的欧几里得算法描述。
- 对前后端分离和FastDFS的使用的再理解
- vim编辑时遇到E325: ATTENTION Found a swap file by the name ./.backu.sh.swp错误代码的解决办法
- 滴滴这名员工的N+1飞了,离职带走公司文档
- nginx配置文件服务器
- Atitit 作用域的理解attilax总结 1.1. 作用域是指对某一变量和方法具有访问权限的代码空间,	1 1.2. 作用域的使用提高了程序逻辑的局部性,增强程序的可靠性,减少名字冲突。	1 1
- 89c51交通灯汇编语言程序,89C51单片机交通灯汇编程序
- DELL D630 显卡门事件 终于碰上了~
- [从零开始学习FPGA编程-22]:进阶篇 - 架构 - FPGA内部硬件电路的设计与建模
- javascript 表单提交和验证的方法
- 线性代数笔记1.1n阶行列式
热门文章
- 西安电子科技大学计算机接口与通用技术答案,西安电子科技大学--西电《计算机接口与通信技术》平时作业...
- 温铁军、林毅夫、陈平,从学术、现实等多方面来分析,谁的价值高?
- 激光点云感知 voxnet本质
- 计算机组成801pan,计算机组成06801.ppt
- python循环输入字典_python - 使用'for'循环迭代字典
- Python入门100题 | 第061题
- Python入门100题 | 第024题
- 支付宝扫一下就能体验的深度学习模型
- Python中的if __name__ == ‘__main__‘
- Netty 学习和进阶策略