linux device driver —— ioctl
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux device driver —— ioctl相关的知识,希望对你有一定的参考价值。
实现了应用程序和设备驱动通过ioctl通信。还是对设备驱动没什么感觉,贴一下代码吧。
在Ubuntu 16.04 64bit中测试通过
ioctldemo.c
#include <linux/module.h> #include <linux/init.h> #include <linux/stat.h> #include <linux/types.h> #include <linux/kdev_t.h> #include <linux/fs.h> #include <linux/moduleparam.h> #include <linux/cdev.h> #include <asm-generic/uaccess.h> #include <asm-generic/ioctl.h> #include <asm-generic/current.h> #define IOCTLDEMO_MAJOR 0 #define MODULE_NAME "ioctldemo" #define DEMO_MAGIC ‘m‘ #define DEMO_SIZE int #define DEMO_NR_MAX 1 #define MY_IOCTL_READ _IOR(DEMO_MAGIC,1,DEMO_SIZE); static int ioctldemo_major = IOCTLDEMO_MAJOR; void ioctldemo_exit(void); int ioctldemo_init(void); long my_unlocked_ioctl(struct file*, unsigned int, unsigned long); int my_cdev_open(struct inode*, struct file*); int my_cdev_release(struct inode*,struct file*); MODULE_LICENSE("Dual BSD/GPL"); module_param(ioctldemo_major,int,S_IRUGO); module_init(ioctldemo_init); module_exit(ioctldemo_exit); struct cdev *my_cdev; static struct file_operations cdev_ops = { .owner = THIS_MODULE, .open = my_cdev_open, .release = my_cdev_release, .unlocked_ioctl = my_unlocked_ioctl, }; int __init ioctldemo_init(void) { int ret; dev_t devno; printk(KERN_NOTICE "=== ioctldemo_init start"); devno = MKDEV(ioctldemo_major,0); if(ioctldemo_major) { printk(KERN_NOTICE "=== ioctldemo_init try register"); ret = register_chrdev_region(devno,1,MODULE_NAME); }else { printk(KERN_NOTICE "=== ioctldemo_init auto register"); ret = alloc_chrdev_region(&devno,0,1,MODULE_NAME); ioctldemo_major = MAJOR(devno); } if(ret < 0) { printk(KERN_NOTICE "=== ioctldemo_init register fail"); return ret; } my_cdev = cdev_alloc(); my_cdev->owner = THIS_MODULE; my_cdev->ops = &cdev_ops; ret = cdev_add(my_cdev,MKDEV(ioctldemo_major,0),1); if(ret < 0) { printk(KERN_NOTICE "=== ioctldemo_init add cdev fail"); return ret; } printk(KERN_NOTICE "=== ioctldemo_init finish"); return 0; } void __exit ioctldemo_exit(void) { printk (KERN_NOTICE "=== ioctldemo_exit"); cdev_del(my_cdev); unregister_chrdev_region(MKDEV(ioctldemo_major,0),1); } long my_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int err = 0; if(_IOC_TYPE(cmd) != DEMO_MAGIC) return -ENOTTY; if(_IOC_NR(cmd) > DEMO_NR_MAX) return -ENOTTY; if(_IOC_DIR(cmd) & _IOC_READ) err = !access_ok(VERIFY_WRITE,(void __user*)arg, _IOC_SIZE(cmd)); if(err) return -EFAULT; printk(KERN_NOTICE "=== ioctldemo_ioctl current process is: %s, pid is: %d\n",current->comm,current->pid); return __put_user(666,(int *)arg); } int my_cdev_open(struct inode *node, struct file *filp) { return 0; } int my_cdev_release(struct inode *node, struct file *filp) { return 0; }
Makefile
ifneq ($(KERNELRELEASE),) mymodule-objs := ioctldemo obj-m := ioctldemo.o else PWD := $(shell pwd) KVER ?= $(shell uname -r) KDIR := /lib/modules/$(KVER)/build all: $(MAKE) -C $(KDIR) M=$(PWD) clean: rm -rf *.cmd *.o *.mod.c .tmp_versions *.order *.symvers endif
install.sh
#!/bin/bash module="ioctldemo" device="ioctldemo" name="ioctldemo" insmod $module.ko if [ $? == 1 ] then exit fi major=$(awk "{if(\$2==\"$name\"){print \$1}}" /proc/devices) mknod /dev/$device c $major 0 chmod 666 /dev/$device
uninstall.sh
#!/bin/bash module="ioctldemo" device="ioctldemo" file="/dev/$device" if [ -e $file ] then rm -rf /dev/$device echo ‘rm device‘ fi echo ‘rm module‘ /sbin/rmmod $module
测试程序:
#include <stdio.h> #include <fcntl.h> #include <sys/ioctl.h> #include <asm-generic/ioctl.h> #include <error.h> #define CMD _IOR(‘m‘,1,int) int main() { int fd, ret, arg; fd = open("/dev/ioctldemo",O_RDWR); if(fd < 0) { puts("open fail"); return fd; } ret = ioctl(fd,CMD,&arg); if(ret == 0) printf("ioctl result :%d",arg); else perror("ioctl fail"); close(fd); return 0; }
以上是关于linux device driver —— ioctl的主要内容,如果未能解决你的问题,请参考以下文章
Linux设备模型 Bus, Class, Device和Device Driver的概念
linux driver ------ 字符设备驱动之“ 创建设备节点流程 ”