字符设备驱动ioctl实现用户层内核层通信
测试代码实现
memdev.h
#ifndef _MEMDEV_H_
#define _MEMDEV_H_
#include<linux/ioctl.h>
#ifndef MEMDEV_MAJOR
#define MEMDEV_MAJOR 0
#endif
#ifndef MEMDEV_NR_DEVS
#define MEMDEV_NR_DEVS 2
#endif
#ifndef MEMDEV_SIZE
#define MEMDEV_SIZE 4096
#endif
struct mem_dev
{
char *data;
unsigned long size;
};
#define MEMDEV_IOC_MAGIC 'k'
#define MEMDEV_IOCPRINT _IO(MEMDEV_IOC_MAGIC,0)
#define MEMDEV_IOCGETDATA _IOR(MEMDEV_IOC_MAGIC,1,int)
#define MEMDEV_IOC_MAXNR 3
#endif
memdev.c
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/types.h>
#include<linux/fs.h>
#include<linux/errno.h>
#include<linux/mm.h>
#include<linux/sched.h>
#include<linux/init.h>
#include<linux/cdev.h>
#include<linux/slab.h>
#include<asm/io.h>
#include<asm/system.h>
#include<asm/uaccess.h>
#include "memdev.h"
static int mem_major = MEMDEV_MAJOR;
module_param(mem_major,int,S_IRUGO);
struct mem_dev *mem_devp;
struct cdev cdev;
int mem_open(struct inode *inode,struct file *filp)
{
struct mem_dev *dev;
int num = MINOR(inode->i_rdev);
if(num >= MEMDEV_NR_DEVS)
return -ENODEV;
dev = &mem_devp[num];
filp->private_data = dev;
return ;
}
int mem_release(struct inode *inode,struct file *filp)
{
return ;
}
long memdev_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
{
int err = ;
int ret = ;
int ioarg = ;
printk("kernel cmd is : %ld\n",cmd);
switch(cmd)
{
case MEMDEV_IOCPRINT:
printk("CMD MEMDEV_IOCPRINT DONE\n\n");
break;
case MEMDEV_IOCGETDATA:
ioarg = ;
if(copy_to_user((int *)arg,&ioarg,sizeof(int)))
return -EFAULT;
break;
default:
return -EINVAL;
}
return ret;
}
static const struct file_operations mem_fops =
{
.owner = THIS_MODULE,
.open = mem_open,
.release = mem_release,
.unlocked_ioctl = memdev_ioctl,
};
static int memdev_init(void)
{
int result;
int i;
dev_t devno = MKDEV(mem_major,);
if (mem_major)
{
result = register_chrdev_region(devno,,"memdev");
printk("first mem_major is : %ld\n",mem_major);
}
else
{
result = alloc_chrdev_region(&devno,,,"memdev");
mem_major = MAJOR(devno);
printk("second mem_major is : %ld\n",mem_major);
}
if(result < )
return result;
cdev_init(&cdev,&mem_fops);
cdev.owner = THIS_MODULE;
cdev.ops = &mem_fops;
cdev_add(&cdev,MKDEV(mem_major,),MEMDEV_NR_DEVS);
mem_devp = kmalloc(MEMDEV_NR_DEVS * sizeof(struct mem_dev),GFP_KERNEL);
if(!mem_devp)
{
result = -ENOMEM;
goto fail_malloc;
}
memset(mem_devp,,sizeof(struct mem_dev));
for(i=;i<MEMDEV_NR_DEVS;i++)
{
mem_devp[i].size = MEMDEV_SIZE;
mem_devp[i].data = kmalloc(MEMDEV_SIZE,GFP_KERNEL);
memset(mem_devp[i].data,,MEMDEV_SIZE);
}
return ;
fail_malloc:
unregister_chrdev_region(devno,);
return result;
}
static void memdev_exit(void)
{
cdev_del(&cdev);
kfree(mem_devp);
unregister_chrdev_region(MKDEV(mem_major,),);
}
MODULE_LICENSE("GPL");
module_init(memdev_init);
module_exit(memdev_exit);
Makefile
obj-m += memdev.o
CURRENT_PATH := $(shell pwd)
LINUX_KERNEL := $(shell uname -r)
LINUX_KERNEL_PATH := /usr/src/linux-headers-$(LINUX_KERNEL)
all:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
clean:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean
app-ioctl.c
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include "memdev.h"
int main(void)
{
int fd = ;
int cmd;
int arg = ;
char Buf[]; fd = open("/dev/memdev0",O_RDWR);
if(fd < )
{
printf("Open Dev Mem Erro\n");
return -;
} printf("call memdev_iocprint\n");
cmd = MEMDEV_IOCPRINT;
printf("userspace cmd is : %ld\n",cmd);
if(ioctl(fd,cmd,&arg) < )
{
printf("call cmd MEMDEV_IOCPRINT fail\n");
return -;
}
printf("call MEMDEV_IOCGETDATA\n");
cmd = MEMDEV_IOCGETDATA;
if(ioctl(fd,cmd,&arg) < )
{
printf("call cmd MEMDEV_IOCGETDATA fail\n");
return -;
}
printf("in user space MEMDEV_IOCGETDATA get data is %d\n\n",arg);
close(fd);
return ;
}
编译memdev,对应的设备驱动
字符设备驱动ioctl实现用户层内核层通信的更多相关文章
- linux 高级字符设备驱动 ioctl操作介绍 例程分析实现【转】
转自:http://my.oschina.net/u/274829/blog/285014 1,ioctl介绍 ioctl控制设备读写数据以及关闭等. 用户空间函数原型:int ioctl(int f ...
- linux设备驱动第三篇:如何实现一个简单的字符设备驱动
在linux设备驱动第一篇:设备驱动程序简介中简单介绍了字符驱动,本篇简单介绍如何写一个简单的字符设备驱动.本篇借鉴LDD中的源码,实现一个与硬件设备无关的字符设备驱动,仅仅操作从内核中分配的一些内存 ...
- linux设备驱动第三篇:如何写一个简单的字符设备驱动?
在linux设备驱动第一篇:设备驱动程序简介中简单介绍了字符驱动,本篇简单介绍如何写一个简单的字符设备驱动.本篇借鉴LDD中的源码,实现一个与硬件设备无关的字符设备驱动,仅仅操作从内核中分配的一些内存 ...
- linux设备驱动第三篇:写一个简单的字符设备驱动
在linux设备驱动第一篇:设备驱动程序简介中简单介绍了字符驱动,本篇简单介绍如何写一个简单的字符设备驱动.本篇借鉴LDD中的源码,实现一个与硬件设备无关的字符设备驱动,仅仅操作从内核中分 ...
- Linux内核分析(五)----字符设备驱动实现
原文:Linux内核分析(五)----字符设备驱动实现 Linux内核分析(五) 昨天我们对linux内核的子系统进行简单的认识,今天我们正式进入驱动的开发,我们今后的学习为了避免大家没有硬件的缺陷, ...
- Linux字符设备驱动框架
字符设备是Linux三大设备之一(另外两种是块设备,网络设备),字符设备就是字节流形式通讯的I/O设备,绝大部分设备都是字符设备,常见的字符设备包括鼠标.键盘.显示器.串口等等,当我们执行ls -l ...
- 深入理解Linux字符设备驱动
文章从上层应用访问字符设备驱动开始,一步步地深入分析Linux字符设备的软件层次.组成框架和交互.如何编写驱动.设备文件的创建和mdev原理,对Linux字符设备驱动有全面的讲解.本文整合之前发表的& ...
- Linux驱动设计——字符设备驱动(一)
Linux字符设别驱动结构 cdev结构体 struct cdev { struct kobject kobj; struct module *owner; const struct file_ope ...
- 字符设备驱动、平台设备驱动、设备驱动模型、sysfs的比较和关联
转载自:http://www.kancloud.cn/yueqian_scut/emlinux/106829 学习Linux设备驱动开发的过程中自然会遇到字符设备驱动.平台设备驱动.设备驱动模型和sy ...
随机推荐
- cmp快排 结构体快排
由于深陷于JAVA的面向对象思想,常常会用到结构体,记一下这个模板,方便直接调用进行结构体排序: struct point { int val,turn; }; bool cmp(struct poi ...
- lintcode-99-重排链表
99-重排链表 给定一个单链表L: L0→L1→-→Ln-1→Ln, 重新排列后为:L0→Ln→L1→Ln-1→L2→Ln-2→- 必须在不改变节点值的情况下进行原地操作. 样例 给出链表 1-> ...
- 《学习OpenCV》课后习题解答7
题目:(P105) 创建一个结构,结构中包含一个整数,一个CvPoint和一个 CvRect:称结构体为"my_struct". a. 写两个函数:void Write_my_st ...
- 【linux】亲测成功_CentOS7.2/rhel7.2 忘记root密码及重置root密码的方法?
本文转自:https://www.jb51.net/article/146320.htm CentOS 7 root密码的重置方式和CentOS 6完全不一样,以进入单用户模式修改root密码为例. ...
- 好用的在线pdf转化器
https://smallpdf.com/cn/compress-pdf
- Delphi中取得程序版本号
Delphi做的程序,如果想包含版本信息, 必须在Delphi的集成编辑环境的菜单“Project/Options/Version Info”里面添加版本信息.即在Version Info 选项卡中选 ...
- 全局 Ajax 事件处理器
jQuery中将Ajax请求和响应分成了若干(5)个阶段 并且允许开发者在Ajax请求和响应的不同阶处理不同的逻辑, 这些方法用于注册事件处理器,用来处理页面上的任何 Ajax 请求,当某些事件触发后 ...
- P3509 [POI2010]ZAB-Frog
题目描述 On the bed of one particularly long and straight Byteotian brook there lie rocks jutting above ...
- SRM710 div1 ReverseMancala(trick)
题目大意, 给定一个有n个点的环,n不超过10,每个点上有一个权重 起始时权重将会给出,然后有2种操作 第一种操作是,选择一个位置i,获得权重w = a[i],把a[i]变成0,然后接下来在环上顺着走 ...
- 【题解】NOI2017游戏
2-SAT.洛谷P3845 一开始以为——怎么有3个呢?后来发现因为每个地图都有一种车是不能用的,所以就等于每一个地图都有两个适应的车啦. 那么对于x类型的地图呢——只有8个,直接2^8暴力枚举每一种 ...