Linux设备驱动开发之Ioctl字符设备驱动实例

1、驱动头文件hello.h

#ifndef __HELLO_H
#define __HELLO_H

#define HELLO_MAGIC 'k' /*定义magic*/

/*定义命令*/
#define HELLO_ONE _IO(HELLO_MAGIC, 1) /*幻数,序号*/
#define HELLO_TWO _IO(HELLO_MAGIC, 2)

#endif

2、驱动源代码hello-ioctl.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/ioctl.h>
#include <asm/uaccess.h>

#include "hello.h"
static int hello_major = 250;//主设备号
static int hello_minor = 0;//次设备号
static int number_of_devices = 1;// 设备的数量
static char data[128] = "\0";

static struct cdev cdev;// 静态定义字符设备
static dev_t dev = 0;// 设备号

static int hello_open(struct inode *inode, struct file *file)
{
printk (KERN_INFO "Hey! device opened\n");
return 0;
}


static int hello_release(struct inode *inode, struct file *file)
{
printk (KERN_INFO "Hmmm! device closed\n");
return 0;
}


static int hello_ioctl(struct inode *inode, struct file *filp, 
unsigned int cmd, unsigned long arg)
{
        int ret=0;

switch (cmd) {
case HELLO_ONE:
printk (KERN_INFO "HELLO_ONE called\n");
break;

case HELLO_TWO:
printk (KERN_INFO "HELLO_TWO called\n");
break;

default:
break;
  
}

return ret;
}

struct file_operations hello_fops = {
.owner = THIS_MODULE,
.open  = hello_open,
.release = hello_release,
.ioctl = hello_ioctl,
};

static void char_reg_setup_cdev (void)
{
int error, devno = MKDEV(hello_major, hello_minor);//合并设备号
cdev_init(&cdev, &hello_fops);//初始化字符设备
cdev.owner = THIS_MODULE;
//cdev.ops = &hello_fops;
error = cdev_add(&cdev, devno, 1);// 注册字符设备
if (error)
printk (KERN_NOTICE "Error %d adding char_reg_setup_cdev", error);

}


static int __init hello_2_init (void)
{
int result;

dev = MKDEV(hello_major, hello_minor);//合并设备号
result = register_chrdev_region(dev, number_of_devices, "hello");// 静态申请设备号
if (result<0) {
printk (KERN_WARNING "hello: can't get major number %d\n", hello_major);
return result;
}

char_reg_setup_cdev();
printk (KERN_INFO "hello_ioctl driver done\n");
return 0;
}

static void __exit hello_2_exit (void)
{
dev_t devno = MKDEV(hello_major, hello_minor); //合并设备号
cdev_del (&cdev);// 注销字符设备
unregister_chrdev_region (devno, number_of_devices);// 注销设备号
printk (KERN_INFO "hello_ioctl cleaned up\n");
}

module_init(hello_2_init);
module_exit(hello_2_exit);

MODULE_LICENSE("GPL");
MODULE_VERSION("v1.0");
MODULE_AUTHOR("[email protected]");
MODULE_DESCRIPTION("Char Driver Module");

MODULE_ALIAS("char driver module");

3、Makefile

ifeq ($(KERNELRELEASE),)
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:                               
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:                                             
        $(MAKE) -C $(KERNELDIR) M=$(PWD) clean
else
    obj-m := hello-ioctl.o

endif

4、应用程序

#include <stdio.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>

#include "hello.h"

int main (void) 
{
int fd;
fd = open ("/dev/hello",O_RDWR);
if (fd < 0) {
printf ("fd open failed\n");
return -1;
}
printf ("/dev/hello opened, fd=%d\n",fd);
ioctl (fd, HELLO_ONE);
ioctl (fd, HELLO_TWO);
close (fd);
printf ("/dev/hello closed\n");
return 0;
}

猜你喜欢

转载自blog.csdn.net/xiezhi123456/article/details/80876017