本例程中代码使用如下博客:http://tuxthink.blogspot.com/2011/01/creating-ioctl-command.html
1.ioctl_basic.h
/*************************************************************************
> File Name: ioctl_basic.h
> Author:
> Mail:
> Created Time: Wed 22 Apr 2015 10:25:01 PM CST
************************************************************************/
#ifndef _IOCTL_BASIC_H
#define _IOCTL_BASIC_H
#include <linux/ioctl.h>
#define IOC_MAGIC 'k'
#define IOCTL_HELLO _IO(IOC_MAGIC,0)
#endif
2.ioctl_basic.c
/*************************************************************************
> File Name: ioctl_basic.c
> Author:
> Mail:
> Created Time: Wed 22 Apr 2015 10:29:15 PM CST
************************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h> // required for various structures related to files liked fops.
#include <linux/semaphore.h>
#include <linux/cdev.h>
#include "ioctl_basic.h"
#include <linux/version.h>
#include <linux/device.h>
static int Major;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
#define UNLOCKED 1
#endif
int open(struct inode *inode, struct file *filp)
{
printk(KERN_INFO "Inside open \n");
return 0;
}
int release(struct inode *inode, struct file *filp) {
printk (KERN_INFO "Inside close \n");
return 0;
}
#ifdef UNLOCKED
long ioctl_funcs(struct file *filp,unsigned int cmd, unsigned long arg)
{
int ret=0;
switch(cmd) {
case IOCTL_HELLO:
printk(KERN_INFO "Hello ioctl world");
break;
}
return ret;
}
struct file_operations fops = {
open: open,
unlocked_ioctl: ioctl_funcs,
release: release
};
#else
int ioctl_funcs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
int data=10,ret;
switch(cmd) {
case IOCTL_HELLO:
printk(KERN_INFO "Hello ioctl world");
break;
}
return ret;
}
struct file_operations fops = {
open: open,
ioctl: ioctl_funcs,
release: release
};
#endif
struct cdev *kernel_cdev;
static struct class *cl;
int char_arr_init (void) {
int ret;
dev_t dev_no,dev;
struct device *dev_ret;
kernel_cdev = cdev_alloc();
kernel_cdev->ops = &fops;
kernel_cdev->owner = THIS_MODULE;
printk (" Inside init module\n");
ret = alloc_chrdev_region( &dev_no , 0, 1,"char_arr_dev" );
if (ret < 0) {
printk("Major number allocation is failed\n");
return ret;
}
Major = MAJOR(dev_no);
dev = MKDEV(Major,0);
printk (" The major number for your device is %d\n", Major);
ret = cdev_add( kernel_cdev,dev,1 );
if(ret < 0 )
{
printk(KERN_INFO "Unable to allocate cdev");
return ret;
}
if (IS_ERR(cl = class_create(THIS_MODULE, "char")))
{
cdev_del(kernel_cdev);
unregister_chrdev_region(dev_no, 1);
return PTR_ERR(cl);
}
if (IS_ERR(dev_ret = device_create(cl, NULL, dev_no, NULL, "query")))
{
class_destroy(cl);
cdev_del(kernel_cdev);
unregister_chrdev_region(dev_no, 1);
return PTR_ERR(dev_ret);
}
return 0;
}
void char_arr_cleanup(void) {
printk(KERN_INFO " Inside cleanup_module\n");
cdev_del(kernel_cdev);
unregister_chrdev_region(Major, 1);
}
MODULE_LICENSE("GPL");
module_init(char_arr_init);
module_exit(char_arr_cleanup);
3.Makefile
ifneq ($(KERNELRELEASE),)
obj-m := ioctl_basic.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
4.make 命令生成ioctl_basic.ko模块
5.用户态例程user_basic_ioctl.c
/*************************************************************************
> File Name: user_basic_ioctl.c
> Author:
> Mail:
> Created Time: Wed 22 Apr 2015 10:32:34 PM CST
************************************************************************/
#include <stdio.h>
#include <fcntl.h>
#include "ioctl_basic.h" //ioctl header file
int main (int argc, char * argv[] ) {
int fd;
fd = open("/dev/query", O_RDWR);
if (fd == -1)
{
printf("Error in opening file \n");
exit(-1);
}
ioctl(fd,IOCTL_HELLO); //ioctl call
close(fd);
return 0;
}
6.gcc user_basic_ioctl.c -o user_app生成用户态程序user_app
7.加载ioctl模块
sudo insmod ioctl_basic.ko
通过dmesg命令查看日志,可以看到如下:
[ 5256.438408] Inside init module
[ 5256.438413] The major number for your device is 248
8.运行sudo ./user_app
通过dmesg可以看到如下日志:
[ 5332.507302] Inside open
[ 5332.507312] Hello ioctl world
[ 5332.507318] Inside close
9.卸载ioctl模块
sudo rmmod ioctl_basic.ko
通过dmesg系统日志可以看到
[ 6567.708057] Inside cleanup_module