CONTENTS
参考网址:
【 http://blog.csdn.net/yusiguyuan/article/details/16829299 】
【 http://www.cnblogs.com/geneil/archive/2011/12/04/2275372.html 】
【 http://116.62.110.235/blog/driving-study-notes-miscellaneous-equipment/ 】
Makefile:
obj-m := helloioctl.o KERNEL_DIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) all: make -C $(KERNEL_DIR) SUBDIRS=$(PWD) modules clean: rm *.o *.ko *.mod.c .PHONY:clean
helloioctl.h:
#ifndef _HELLO_IOCTL_H_ #define _HELLO_IOCTL_H_ #include <linux/ioctl.h> /* 定义幻数 */ #define IOC_MAGIC 'c' /* 定义命令 */ #define IOC_PRINTNUM _IO(IOC_MAGIC, 1) #define IOC_GETNUM _IOR(IOC_MAGIC, 2, int) #define IOC_SETNUM _IOW(IOC_MAGIC, 3, int) #define IOC_MAX 3 #endif /* _HELLO_IOCTL_H_ */
helloioctl.c:
#include <linux/kernel.h> #include <linux/module.h> #include <asm/uaccess.h> #include <linux/fs.h> #include <linux/miscdevice.h> #include "helloioctl.h" static int currNum = 0; /*IO操作*/ long my_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int err = 0; int ret = 0; /* 检测命令的有效性 */ if (_IOC_TYPE(cmd) != IOC_MAGIC) return -EINVAL; if (_IOC_NR(cmd) > IOC_MAX) return -EINVAL; /* 根据命令类型,检测参数空间是否可以访问 */ if (_IOC_DIR(cmd) & _IOC_READ) err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd)); else if (_IOC_DIR(cmd) & _IOC_WRITE) err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd)); if (err) return -EFAULT; /* 根据命令,执行相应的操作 */ switch(cmd) { case IOC_PRINTNUM: printk(KERN_ALERT "currNum = %d\n",currNum); break; case IOC_GETNUM: ret = __put_user(currNum, (int *)arg); break; case IOC_SETNUM: ret = __get_user(currNum, (int *)arg); break; default: return -EINVAL; } return ret; } struct file_operations myfops = { .owner = THIS_MODULE, .unlocked_ioctl = my_ioctl, }; struct miscdevice my_misc = { .minor = MISC_DYNAMIC_MINOR, .name = "helloioctl", .fops = &myfops, }; static int hello_init(void) { printk(KERN_ALERT "Hello, world\n"); currNum = 0; misc_register(&my_misc); return 0; } static void hello_exit(void) { printk(KERN_ALERT "Goodbye, world\n"); misc_deregister(&my_misc); } module_init(hello_init); module_exit(hello_exit);
插入驱动模块:
root@ubuntu:/home/cstriker1407/drivers/helloioctl# make make -C /lib/modules/3.13.0-37-generic/build SUBDIRS=/home/cstriker1407/drivers/helloioctl modules make[1]: 正在进入目录 `/usr/src/linux-headers-3.13.0-37-generic' CC [M] /home/cstriker1407/drivers/helloioctl/helloioctl.o Building modules, stage 2. MODPOST 1 modules CC /home/cstriker1407/drivers/helloioctl/helloioctl.mod.o LD [M] /home/cstriker1407/drivers/helloioctl/helloioctl.ko make[1]:正在离开目录 `/usr/src/linux-headers-3.13.0-37-generic' root@ubuntu:/home/cstriker1407/drivers/helloioctl# insmod helloioctl.ko root@ubuntu:/home/cstriker1407/drivers/helloioctl# tail -f /var/log/kern.log Nov 3 05:24:04 ubuntu kernel: [ 3633.887152] Hello, world 。。。 cstriker1407@ubuntu:/dev$ ls 。。。。。。 helloioctl 。。。。。。
编写测试代码testioctl.c:
#include <stdio.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include "helloioctl.h" int main() { int fd = 0; int cmd; int arg = 0; fd = open("/dev/helloioctl",O_RDWR); if (fd < 0) { printf("Open helloioctl Error!\n"); return -1; } printf("<--- Call IOC_PRINTNUM --->\n"); cmd = IOC_PRINTNUM; if (ioctl(fd, cmd, &arg) < 0) { printf("Call cmd IOC_PRINTNUM fail\n"); return -1; } printf("<--- Call IOC_SETNUM --->\n"); cmd = IOC_SETNUM; arg = 100; if (ioctl(fd, cmd, &arg) < 0) { printf("Call cmd IOC_SETNUM fail\n"); return -1; } printf("<--- Call IOC_GETNUM --->\n"); cmd = IOC_GETNUM; if (ioctl(fd, cmd, &arg) < 0) { printf("Call cmd IOC_GETNUM fail\n"); return -1; } printf("<--- In User Space IOC_GETNUM Get Data is %d --->\n\n",arg); close(fd); return 0; }
测试IOCTL:
root@ubuntu:/home/cstriker1407/drivers/helloioctl# gcc testioctl.c root@ubuntu:/home/cstriker1407/drivers/helloioctl# ./a.out <--- Call IOC_PRINTNUM ---> <--- Call IOC_SETNUM ---> <--- Call IOC_GETNUM ---> <--- In User Space IOC_GETNUM Get Data is 100 ---> root@ubuntu:/home/cstriker1407/drivers/helloioctl# rmmod helloioctl root@ubuntu:/home/cstriker1407/drivers/helloioctl# tail -f /var/log/kern.log Nov 3 05:29:35 ubuntu kernel: [ 3964.652611] currNum = 0 Nov 3 05:30:51 ubuntu kernel: [ 4040.750168] Goodbye, world
发表评论