结构体file_operations为应用程序提供了操作设备的接口,包括打开设备、关闭设备、读设备、写设备等操作。
驱动程序部分:
/* 源代码文件名为"xxx.c"*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#define SHANWUYAN_MAJOR 200
#define SHANWUYAN_NAME "shanwuyan"
/*打开设备*/
static int shanwuyan_open(struct inode *inode, struct file *filp)
{
printk(KERN_EMERG "shanwuyan_open\r\n");
return 0;
}
/*释放(关闭)设备*/
static int shanwuyan_release(struct inode *inode, struct file *filp)
{
printk(KERN_EMERG "shanwuyan_close\r\n");
return 0;
}
/*读设备*/
static ssize_t shanwuyan_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{
printk(KERN_EMERG "shanwuyan_read\r\n");
return 0;
}
/*写设备*/
static ssize_t shanwuyan_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{
printk(KERN_EMERG "shanwuyan_write\r\n");
return 0;
}
static struct file_operations shanwuyan_fops =
{
.owner = THIS_MODULE, //默认
.open = shanwuyan_open, //打开设备
.release = shanwuyan_release, //关闭设备
.read = shanwuyan_read, //读设备
.write = shanwuyan_write, //写设备
};
static int __init shanwuyan_init(void) //驱动入口函数
{
int ret = 0;
ret = register_chrdev(SHANWUYAN_MAJOR, SHANWUYAN_NAME, &shanwuyan_fops);
if(ret < 0)
printk(KERN_EMERG "init failed\r\n"); //注册失败
else
printk(KERN_EMERG "shanwuyan_init\r\n");//注册成功
return 0;
}
static void __exit shanwuyan_exit(void) //驱动出口函数
{
unregister_chrdev(SHANWUYAN_MAJOR, SHANWUYAN_NAME); //注销字符设备
printk(KERN_EMERG "shanwuyan_exit\r\n");
}
module_init(shanwuyan_init); //注册入口函数
module_exit(shanwuyan_exit); //注册出口函数
MODULE_LICENSE("GPL"); //同意GPL开源协议
MODULE_AUTHOR("......"); //添加作者名称
makefile部分:
#!/bin/bash
obj-m += shanwuyan.o
KDIR := /home/topeet/Android/itop4412_kernel_4_14_2_bsp/linux-4.14.2_iTop-4412_scp #这里要对应你的Linux内核目录
PWD ?= $(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean
应用程序部分:
//文件名为"xxx_APP.c"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
/*
*argc:应用程序参数个数,包括应用程序本身
*argv[]:具体的参数内容,字符串形式
*./shanwuyan_APP <filename> <r:w> r表示读,w表示写
*/
int main(int argc, char *argv[])
{
int ret = 0;
int fd = 0;
char *filename;
if(argc != 3) //共有三个参数
{
printf("Error usage!\r\n");
return -1;
}
filename = argv[1]; //获取文件名称
fd = open(filename, O_RDWR);
if(fd < 0)
{
printf("cannot open file %s\r\n", filename);
return -1;
}
if(!strcmp(argv[2], "r")) //读设备
{
read(fd, NULL, 0); //只是使用读函数,但不读出数据
}
else if(!strcmp(argv[2], "w")) //写设备
{
write(fd, NULL, 0); //只是使用
}
else
{
printf("ERROR usage!\r\n");
}
/*关闭设备*/
close(fd);
return 0;
}
4.应用
编译驱动文件,交叉编译应用程序,拷贝到开发板中,并加载驱动。
驱动加载完成后,使用命令"mknod /dev/shanwuyan c 200 0",在"/dev"目录下创建"shanwuyan"设备节点。其中参数"c"是指创建一个字符设备节点,200表示主设备号,0表示次设备号。然后使用ls命令查看是否创建成功。
分别输入命令"./shanwuyan_APP /dev/shanwuyan r"和命令"./shanwuyan_APP /dev/shanwuyan w",可以看到终端打印了如下信息。可以看到,应用程序打开设备、关闭设备、读设备、写设备的操作都有所体现。
在本章中,我们只是单纯得调用了read和write函数,但是并没有真正的读写数据。读写数据操作将在下一章中出现。
本章的全部代码在这里。
原文地址:https://blog.csdn.net/a154299/article/details/108579348