file_operations使用示例(实现read/write/ioctl)

本文档展示了如何使用Linux内核模块(ko)实现用户态和内核态之间的交互。通过创建设备驱动,实现了open、release、read、write及ioctl系统调用,用户态应用程序可通过这些调用来执行内核中的特定任务。内核模块通过系统调用传递结构体参数,完成任务后将结果返回给用户态。示例代码中包括了设备注册、注销、字符设备操作函数的实现。
摘要由CSDN通过智能技术生成

内核态ko完成用户在内核态想完成的任务,而内核态ko加载后,通过用户态open等系统调用间接执行内核态的任务,相关执行任务需要的配置参数,结构体等,通过系统调用传入到内核态,完成任务后,将任务数据写回到用户态,以便下一步操作;

文件目录:

Makefile

obj-m:=test_tools.o
KDIR:=/lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)

default:
    $(MAKE) -C $(KDIR) M=$(PWD) modules

clean:
    rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions *.order *symvers *Module.markers

test_tools.ko(编译命令:make)

/***************************************************************************//**
*  \file       test_tools.c
*
*  \details    Simple Linux device driver (File Operations)
*
*  \author     EmbeTronicX
*
* *******************************************************************************/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>

dev_t dev = 0;
static struct class *dev_class;
static struct cdev test_cdev;

struct task_info {
	char alg[50];
	int res;
};

/*
** Function Prototypes
*/
static int      __init test_tools_init(void);
static void     __exit test_tools_exit(void);
static int      test_open(struct inode *inode, struct file *file);
static int      test_release(struct inode *inode, struct file *file);
static ssize_t  test_read(struct file *filp, char __user *buf, size_t len,loff_t * off);
static ssize_t  test_write(struct file *filp, const char *buf, size_t len, loff_t * off);
static ssize_t  test_unlocked_ioctl(struct file *filp, unsigned int cmd, struct task_info* arg);
static int do_A(struct task_info*);
static int do_B(struct task_info*);

typedef int (*alg_do) (struct task_info*);

struct alg_handle {
	char alg_name[50];
	alg_do alg_func;
};

struct alg_handle alg_handle_tables[] = {
	{"AAA", do_A},
	{"BBB", do_B},
};

static struct file_operations fops =
{
    .owner      = THIS_MODULE,
    .read       = test_read,
    .write      = test_write,
    .open       = test_open,
    .release    = test_release,
	.unlocked_ioctl = test_unlocked_ioctl,
};
/*
** This fuction will be called when we open the Device file
*/
static int test_open(struct inode *inode, struct file *file)
{
        printk(KERN_INFO "Driver Open Function Called...!!!\n");
        return 0;
}
/*
** This fuction will be called when we close the Device file
*/
static int test_release(struct inode *inode, struct file *file)
{
        printk(KERN_INFO "Driver Release Function Called...!!!\n");
        return 0;
}
/*
** This fuction will be called when we read the Device file
*/
static ssize_t test_read(struct file *filp, char __user *buf, size_t len, loff_t *off)
{
	char *a = NULL;
	int i = 0;
	
	printk(KERN_INFO "Driver Read Function Called...!!!\n");
	a = kmalloc(10,GFP_KERNEL);
	for(;i<9;i++) {
		a[i] = i+'a';
	}
	copy_to_user(buf,a,9);
	return 0;
}
/*
** This fuction will be called when we write the Device file
*/
static ssize_t test_write(struct file *filp, const char __user *buf, size_t len, loff_t *off)
{
	char *a=NULL;
	int i = 0;
	
	printk(KERN_INFO "Driver Write Function Called...!!!\n");
	
	a = kmalloc(len,GFP_KERNEL);
	copy_from_user(a,buf,len);

	for(;i<9;i++) {
		printk("%d ", a[i]);
	}
	printk("\n");
	return len;
}
/*
** This fuction will be called when we ioctl the Device file
*/
static ssize_t test_unlocked_ioctl(struct file *filp, unsigned int cmd, struct task_info* arg)
{
	struct task_info *tf;
	int num_cmds = 0;
	int index;
	alg_do fn;
	int ret = 0;
	
	tf = kzalloc(sizeof(struct task_info), GFP_KERNEL);
	if (!tf) {
		printk("tf alloc failed.\n");
		return -ENOMEM;
	}

	if (copy_from_user(tf, arg, sizeof(*tf))) {
		printk("copy_from_user failed.\n");
		return -EFAULT;
	}
	num_cmds = ARRAY_SIZE(alg_handle_tables);
	for (index = 0; index < num_cmds; index ++) {
		if (!strcmp(tf->alg, alg_handle_tables[index].alg_name)) {
			fn = alg_handle_tables[index].alg_func;
			ret = fn(tf);
			printk("ret:%d res:%d\n", ret, tf->res);
			break;
		}
	}

	ret = copy_to_user(arg, tf, sizeof(struct task_info));
	printk("copy_to_user ret:%d.\n", ret);

	return ret;
}

static int do_A(struct task_info *tf) {
	tf->res = 10;
	
	printk("do somethin in algA\n");

	return 0;
}
static int do_B(struct task_info *tf) {
	tf->res = 0;
	
	printk("do somethin in algB\n");

	return 0;
}

/*
** Module Init function
*/
static int __init test_tools_init(void)
{
        /*Allocating Major number*/
        if((alloc_chrdev_region(&dev, 0, 1, "test_tools")) <0){
                printk(KERN_INFO "Cannot allocate major number\n");
                return -1;
        }
        printk(KERN_INFO "Major = %d Minor = %d \n",MAJOR(dev), MINOR(dev));
        /*Creating cdev structure*/
        cdev_init(&test_cdev,&fops);
        /*Adding character device to the system*/
        if((cdev_add(&test_cdev,dev,1)) < 0){
            printk(KERN_INFO "Cannot add the device to the system\n");
            goto r_class;
        }
        /*Creating struct class*/
        if((dev_class = class_create(THIS_MODULE,"test_class")) == NULL){
            printk(KERN_INFO "Cannot create the struct class\n");
            goto r_class;
        }
        /*Creating device*/
        if((device_create(dev_class,NULL,dev,NULL,"test_tools")) == NULL){
            printk(KERN_INFO "Cannot create the Device 1\n");
            goto r_device;
        }
        printk(KERN_INFO "Device Driver Insert...Done!!!\n");
        return 0;
r_device:
        class_destroy(dev_class);
r_class:
        unregister_chrdev_region(dev,1);
        return -1;
}
/*
** Module exit function
*/
static void __exit test_tools_exit(void)
{
        device_destroy(dev_class,dev);
        class_destroy(dev_class);
        cdev_del(&test_cdev);
        unregister_chrdev_region(dev, 1);
        printk(KERN_INFO "Device Driver Remove...Done!!!\n");
}
module_init(test_tools_init);
module_exit(test_tools_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("lanzhihui@huawei.com");
MODULE_DESCRIPTION("test_tools");
MODULE_VERSION("1.0");

main.c(编译命令:gcc main.c -o main)

#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#define CHR_DEV_NAME "/dev/test_tools"

struct task_info {
	char alg[50];
	int res;
};

int main()
{
    int ret;
    char buf[32];
    int fd = open(CHR_DEV_NAME, O_RDWR);
    if(fd < 0)
    {
        printf("open file %s failed!\n", CHR_DEV_NAME);
        return -1;
    }
	
	//read
    read(fd, buf, 32);
	int i=0;
	for(;i<10;i++) {
		printf("%d ", buf[i]);
	}
	printf("\n");

	//write
	ret = write(fd,buf,10);
	printf("ret:%d\n", ret);
	
	//ioctl
	struct task_info tf = {
		.alg = "AAA",
		.res = -1,
	};
	ret = ioctl(fd, 0, &tf);
	printf("ret:%d res:%d\n", ret, tf.res);
	
    close(fd);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值