天天看点

linux设备驱动ioctl,字符设备驱动ioctl实现用户层内核层通信

测试代码实现

memdev.h

#ifndef _MEMDEV_H_

#define _MEMDEV_H_

#include

#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

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#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

{

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

#include

#include

#include

#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,对应的设备驱动

make

insmod memdev.ko

在dmesg中会有输出结果init,在/proc/devices中生成对应的设备驱动号249

创建设备节点

cat /proc/devices中生成的memdev节点编号249

mknod /dev/memdev0 c 249 0创建设备节点,并将对应的设备节点与设备驱动号进行绑定。当打开该设备节点进行后续操作时,将会由设备驱动文件进行具体实现

编译app ioctl测试文件

gcc -o app-ioctl app-ioctl.c

./app-ioctl

正常执行结果会显示,dmesg也会显示内核结果

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 ...

随机推荐

MySQL索引的Index method中btree和hash的优缺点

MySQL索引的Index method中btree和hash的区别 在MySQL中,大多数索引(如 PRIMARY KEY,UNIQUE,INDEX和FULLTEXT)都是在BTREE中存储,但使用 ...

开始研究tigase和android客户端的实现

2015.7.5. 昨晚总算把tigaase7.0的开发环境搭起来了.稍微看了下代码结构. 主要是auth,db,compnent,cluster,server,xmpp,这几块,准备先发点时间看看开 ...

关于WPF中RichTextBox失去焦点后如何保持高亮显示所选择的内容

其实很简单,只要将容器控件中的附加属性FocusManager.IsFocusScope设为True就可以了 下面是个简单的用例:

format格式化和函数

{[name][:][[fill]align][sign][#][0][width][,][.precision][type]}用{ }包裹name命名传递给format以命名=值 写法, 非字典映射 ...

SUSE Enterprise Server 12 SP3 64 设置防火墙开放8080端口

SUSE Enterprise Server 12 SP3 64 设置防火墙开放8080端口 第一种方式: 1.sudo chmod a+w /etc/sysconfig/SuSEfirewall2  ...