一个杂项设备,应用层通过write函数传入一个结构体,把结构体写入内核

#1杂项设备
##1.1linux下的三大设备
字符设备,块设备,网络设备。
字符设备特点:是一个顺序的数据流设备,对这种设备的读写是按字符进行的,这些字符是连续地形成一个数据流。他不具备缓冲区,对这种设备的读写是实时的。
块设备特点:具有一定结构的随记存取设备,对这种设备的读写是按块进行的,使用缓冲区来存放暂时的数据,待时机成熟后,从缓存一次性写入设备或者从设备一次性读到缓冲区。
网络设备特点:网络设备是面向数据包的接收和发送而设计,由系统分配一个唯一的名字(如eth0)。
除网络设备外,字符设备和块设备都是通过文件系统的系统调用接口open()、close()、write()、read()等函数可以访问,应用程序可以通过打开设备文件来访问该设备。
#杂项设备注册/注销函数
| 头文件 | #include <linux/miscdevice.h>
|函数原型| int misc_register(struct miscdevice * misc);//注册 int misc_deregister(struct miscdevice *misc); //卸载
| 参数| misc: 杂项设备的指针
|返回值|失败:小于0

#2杂项设备驱动代码例子:fops.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>

typedef struct STUDENT
{
char sex;
char name[20];
int num;
}stu;
stu student;
int tiny4412_open(struct inode *node, struct file *fp)
{
printk(“tiny4412 open is called by user space\n”);
return 0;
}
//ubuf是user buf的缩写
ssize_t tiny4412_read(struct file *fp, char __user *ubuf, size_t size, loff_t *foff)
{
int ret;
ret = copy_to_user(ubuf, &student, sizeof(student));
if(ret != 0){
printk(“copy to user error\n”);
return ret;
}
printk(“tiny4412_read\n”);
return 0;
}

ssize_t tiny4412_write(struct file *fp, const char __user *ubuf, size_t size, loff_t *foff)
{
int ret;
ret = copy_from_user(&student, ubuf, size);
if(ret != 0){
printk(“copy from user error\n”);
return ret;
}
printk(“student.name = %s\n”,student.name);
printk(“student.num = %d\n”,student.num);
printk(“student.sex = %c\n”,student.sex);
return 0;
}

struct file_operations misc_fops={
.owner=THIS_MODULE,
.read = tiny4412_read,
.write = tiny4412_write,
.open = tiny4412_open
};

struct miscdevice my_misc ={
.minor=MISC_DYNAMIC_MINOR,
.fops=&misc_fops,
.name=“biu”
};

static int __init tiny4412_misc_init(void)
{
int ret;
ret=misc_register(&my_misc);
if(ret<0)
{
printk(“misc_register error\n”);
return ret;
}
printk(“misc_register ok\n”);
return 0;
}

static void __exit tiny4412_misc_exit(void)
{

misc_deregister(&my_misc);
printk("tiny4412 misc devices is moved complete\n");

}

module_init(tiny4412_misc_init);
module_exit(tiny4412_misc_exit);
MODULE_LICENSE(“GPL”);


应用程序测试驱动:app.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

typedef struct STUDENT
{
char sex;
char name[20];
int num;
}stu;
stu student2;
int main(int argc, char **argv)
{
int fd;
stu student ={
.sex = ‘m’,
.name = “xiaohong”,
.num = 18117
};

fd = open("/dev/biu", O_RDWR);
if(fd < 0){
	perror("open error:");
	return fd;
}
write(fd, &student, sizeof(stu));
read(fd, &student2, sizeof(stu));
printf("student2.name = %s\n",student2.name);
printf("student2.num = %d\n",student2.num);
printf("student2.sex = %c\n",student2.sex);
close(fd);

return 0;

}


obj-m += fops.o

KERN_DIR=/root/work/tiny4412/linux/linux-3.5
PWD := $(shell pwd)

modules:
$(MAKE) ARCH=arm -C (KERNDIR)M=(KERN_DIR) M=(PWD) modules

clean:
$(MAKE) ARCH=arm -C (KERNDIR)M=(KERN_DIR) M=(PWD) modules clean

开发板测试:
make编译内核,arm-linux-gcc 编译app,把生成的.ko和app传到开发板上。然后insmod fops.ko,执行app

![在这里插入图片描述](https://img-blog.csdnimg.cn/20190602211345862.png)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章