/*驱动从APP获取数据*/
unsigned long copy_from_user(void *to, const void *from, unsigned long n)
/*驱动传输数据到APP*/
unsigned long copy_to_user(void *to, const void *from, unsigned long n)
测试方式:
./hello_test /dev/hello 1234abc APP向驱动程序写入数据
./hello_test /dev/hello APP从驱动程序读出刚才写入的数据
APP与驱动程序传输数据原理:
第一步:class_create函数 创建设备类
/*
* @description : 创建一个class类型的对象
* @param - owner : THIS_MODULE
* @param - name : 类名字
* @return : 成功,返回struct class的指针;其他 失败
*/
struct class *class_create(struct module *owner, const char *name)
/*举例*/
static struct class *hello_class;
hello_class = class_create(THIS_MODULE, "hello_class");
第二步:device_create函数 在/dev下创建设备节点(无需在开发板端执行mknod命令了)
/*
* @description : 生成设备节点并导出到用户空间(在/dev下创建设备节点)
* @param - class : 指向该设备应注册到的struct class的指针(上一个class_create函数返回值)
* @param - parent : 指向此新设备的父struct设备的指针(如果有),没有填NULL
* @param - devt : 要添加的char设备的dev_t(设备号)
* @param - drvdata : 要添加到设备中以进行回调的数据(如果有),没有填NULL
* @param - fmt : 设备名称的字符串
* @return : 成功,返回struct device指针;其他 失败
*/
struct device *device_create(struct class *class, struct device *parent,
dev_t devt, void *drvdata, const char *fmt, ...)
/*举例*/
device_create(hello_class, NULL, MKDEV(major, 0), NULL, "hello");
上代码
hello驱动程序代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
static int major;
static unsigned char buff[100];
static struct class *hello_class;
static int hello_open (struct inode *node, struct file *filp)
{
printk("hello_open\n");
printk("%s %s %d\n",__FILE__, __FUNCTION__, __LINE__);
return 0;
}
static ssize_t hello_read (struct file *filp, char *buf, size_t size, loff_t *offset)
{
size_t len = size > 100 ? 100 : size;
printk("hello_read\n");
copy_to_user(buf, buff, len);
return len;
}
static ssize_t hello_write (struct file *filp, const char *buf, size_t size, loff_t *offset)
{
size_t len = size > 100 ? 100 : size;
memset(buff, 0 ,sizeof(buff));
printk("hello_write\n");
copy_from_user(buff, buf, len);
return len;
}
static int hello_release (struct inode *node, struct file *filp)
{
printk("hello_release\n");
return 0;
}
/*1.定义 file_operations 结构体*/
static const struct file_operations hello_drv = {
.owner = THIS_MODULE,
.read = hello_read,
.write = hello_write,
.open = hello_open,
.release = hello_release,
};
/*3.入口函数*/
static int hello_init(void)
{
//返回主设备号
major = register_chrdev(0,"hello_drv",&hello_drv);
printk("hello_open\n");
printk("%s %s %d\n",__FILE__, __FUNCTION__, __LINE__);
/*在内核中创建设备*/
hello_class = class_create(THIS_MODULE, "hello_class");
if (IS_ERR(hello_class)) {
printk("hello class create failed!\n");
}
/*在设备类下面创建设备*/
device_create(hello_class, NULL, MKDEV(major, 0), NULL, "hello");
if (IS_ERR(dev)) {
printk("hello device_create failed!\n");
}
return 0;
}
/*4.退出函数*/
static int hello_exit(void)
{
//卸载设备
unregister_chrdev(major,"hello_drv");
//销毁设备
device_destroy(hello_class, MKDEV(major, 0));
//删除设备类
class_destroy(hello_class);
//删除注册的设备号
// unregister_chrdev_region(major, 1);
return 0;
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
hello应用程序代码:
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
int len;
char read_buf[10];
if(argc < 2){
printf("please input at least 2 args\n");
printf("%s [string]\n" , argv[0]);
return -1;
}
/*open*/
int fd;
fd = open(argv[1], O_RDWR);
if(fd < 0){
printf("open failed\n");
return -2;
}
/*read*/
if(argc == 2){
read(fd, read_buf, 10); //调用read函数,只为了触发系统调用hello驱动的read函数
printf("read operation : %s\n", read_buf);
}
/*write*/
if(argc == 3){
len = write(fd, argv[2], strlen(argv[2])); //调用write函数,只为了触发系统调用hello驱动的write函数
printf("write length = %d \n", len);
}
close(fd);
return 0;
}
测试结果:
[root@100ask:/mnt]# insmod hello_drv.ko (向内核注册hello驱动)
[root@100ask:/mnt]# cat /proc/devices (查看驱动设备号)
Character devices:
1 mem
4 /dev/vc/0
4 tty
5 /dev/tty
5 /dev/console
5 /dev/ptmx
7 vcs
10 misc
13 input
29 fb
81 video4linux
89 i2c
90 mtd
108 ppp
116 alsa
128 ptm
136 pts
166 ttyACM
180 usb
188 ttyUSB
189 usb_device
207 ttymxc
216 rfcomm
226 drm
238 hello_drv
[root@100ask:/mnt]# ls -l /dev/hello (查看/dev下是否有hello设备节点)
crw------- 1 root root 238, 0 Jan 1 01:37 /dev/hello
#测试hello驱动读写操作
[root@100ask:/mnt]# ./hello_test /dev/hello 1234abc (向驱动写)
write length = 7
[root@100ask:/mnt]# ./hello_test /dev/hello (读驱动)
read operation : 1234abc