Linux系统驱动开发之字符设备虚拟设备实验
(完整)广州大学Linux_实验五

广州大学学生实验报告一、实验目的通过一个简单的设备驱动的实现过程。
学会Linux中设备驱动程序的编写二、使用仪器、器材1.设备:带网卡的PC若干、交换机一台。
2.工具:网线若干,已经安装好Red Hat Linux 9。
0系统的PC一台。
三、实验内容及原理设计和实现一个虚拟命名管道(FIFO)的字符设备。
写一个模块化的字符设备驱动程序四、实验过程(1)设备的实现1、数据结构/*vfifo.c*/#ifndef __KERNEL__#define __KERNEL__#endif#ifndef MODULE#define MODULE#endif#define __NO_VERSION__#include〈linux/config。
h>#include〈linux/module。
h>#include<linux/kernel.h〉#include〈linux/malloc。
h〉#include〈linux/fs。
h〉#include<linux/proc_fs。
h〉#include<linux/errno.h〉#include<linux/types。
h〉#include〈linux/fcntl。
h>#include〈linux/init。
h〉#include〈asm/system.h〉#include<asm/uaccess.h〉#ifndef VFIFO_MAJOR#define VFIFO_MAJOR 241#endif#ifndef VFIFO_NR_DEVS#define VFIFO_NR_DEVS 4#endif#ifndef VFIFO_BUFFER#define VFIFO_BUFFER 4000#endif#include<linux/devfs_fs_kernel。
h〉devfs_handle_t vfifo_devfs_dir;struct file_operations vfifo_fops;int vfifo_major=VFIFO_MAJOR;int vfifo_nr_devs=VFIFO_NR_DEVS;int vfifo_buffer=VFIFO_BUFFER;MODULE_PARM(vfifo_major,"i");MODULE_PARM(vfifo_nr_devs,"i");MODULE_PARM(vfifo_buffer,"i");MODULE_AUT HOR(”EBUDDY”);结构体/*vfifo。
简单的虚拟字符设备驱动的实现

简单的虚拟字符设备驱动的实现Linux業已成为嵌入式系统的主流,而各种Linux驱动程序的类型中,字符设备无疑是应用最广泛的。
本文实现了一个简单的虚拟字符设备的驱动程序,用以演示Linux字符设备驱动的基本原理。
在嵌入式Linux的教学中具有重要的作用。
标签:Linux 驱动程序字符设备虚拟嵌入式Linux作为一种开放源代码的操作系统,在嵌入式系统领域业已成为主流,而为嵌入式Linux系统开发设备驱动程序,也成为一项重要的工作。
Linux系统中的驱动程序主要分为三种:字符设备驱动程序、块设备驱动程序和网络驱动程序。
其中字符设备是一类只能顺序读写,没有缓存的驱动程序,其实现方法相对简单,而应用则最为广泛。
在嵌入式Linux的教学中,字符设备驱动程序也是一项重要内容。
为了让学生能够理解字符设备驱动程序的原理,需要一个简单的字符设备驱动的例子,用以进行演示。
一、基本原理把设备当作文件处理,是Linux系统的重要思想,即“一切皆文件”。
在用户空间中,应用程序对字符设备的操作跟读写普通文件没有什么区别,也是通过open()、close()、read()、write()等函数实现的。
操作系统将这些用户空间中的函数分别映射到内核空间中由驱动程序提供的对应接口。
因此,内核空间中的驱动程序就需要通过对对应接口函数的实现来实现对用户空间中应用程序的支持。
file_opreations是字符设备驱动中最重要的结构,它包含了字符设备各种可能的接口函数。
通常在嵌入式编程中,我们不需要全部实现,只需要实现我们实际用到的接口就可以了,这样可以有效降低程序的大小。
该结构被定义在头文件“linux/fs.h”中,使用时只需声明该结构的一个变量并进行填充即可。
二、环境准备为了进行嵌入式Linux的开发,必须首先安装Linux系统。
这里采用最常用的Windows系统+VMWare虚拟机的形式,系统版本为RedHat Enterprise Linux 6.4,其自带的内核版本为2.6.32-358.el6.i686。
linux课课程设计字符设备驱动

linux课课程设计字符设备驱动一、教学目标本章节的教学目标是使学生掌握Linux系统中字符设备驱动的基本原理和编程方法。
通过本章节的学习,学生将能够:1.理解字符设备驱动的概念和作用;2.掌握字符设备驱动的原理和编程方法;3.能够编写简单的字符设备驱动程序。
二、教学内容本章节的教学内容主要包括:1.字符设备驱动的概念和作用;2.字符设备驱动的原理和编程方法;3.字符设备驱动的实例分析。
具体的教学大纲如下:1.字符设备驱动的概念和作用:介绍字符设备驱动的基本概念,解释其在Linux系统中的作用;2.字符设备驱动的原理:讲解字符设备驱动的工作原理,包括驱动程序的加载、设备文件的创建和使用;3.字符设备驱动的编程方法:介绍编写字符设备驱动程序的基本步骤和方法,包括文件操作、缓冲区管理和中断处理;4.字符设备驱动的实例分析:分析实际的字符设备驱动程序代码,让学生了解和掌握驱动程序的具体实现方法。
三、教学方法为了达到本章节的教学目标,将采用以下教学方法:1.讲授法:讲解字符设备驱动的基本概念、原理和编程方法;2.案例分析法:分析实际的字符设备驱动程序代码,让学生了解和掌握驱动程序的具体实现方法;3.实验法:让学生动手编写和调试字符设备驱动程序,巩固所学的知识和技能。
四、教学资源为了支持本章节的教学内容和教学方法的实施,将准备以下教学资源:1.教材:《Linux设备驱动程序设计与实现》;2.参考书:《Linux内核设计与实现》;3.多媒体资料:教学PPT、视频教程等;4.实验设备:计算机、开发板等。
五、教学评估为了全面、客观地评估学生在Linux字符设备驱动课程中的学习成果,将采用以下评估方式:1.平时表现:通过课堂参与、提问和讨论等方式评估学生的学习态度和理解程度;2.作业:布置相关的编程练习和理论作业,评估学生对知识的掌握和应用能力;3.考试:进行期中和期末考试,以评估学生对课程内容的整体理解和掌握程度。
一个虚拟的字符驱动程序实验报告

6. 用命令 lsmod 察看是否成功加载 7. 使用 dmesg 察看主设备号
8. 使用 mknod /dev/char_dev c 249 1 在/dev 目录下创建设备文件 9. 运行 testchardev.c 测试
实验总结:
通过 1. 自定义驱动程序描述符 2. 预订主设备号 3. 初始化自定义描述符 4. 初始化 gendisk 描述符 5. 初始化块设备操作表 6. 分配和初始化请求队列 7. 设置中断处理程序 8. 注册磁盘
}
3.Makefile
ifneq ($(KERNELRELEASE),) obj-m:=char_dev.o else KD ?=/lib/modules/$(shell uname -r)/build PWD :=$(shell pwd) default:
$(MAKE) -C $(KD) M=$(PWD) modules clean:
{ int i; printk("<0>""read char_dev\n"); for(i = 0; i < length; i++) { put_user('a',buffer++); } return (ssize_t)length;
}
static ssize_t device_write(struct file *file, const char *buffer, /* The buffer */ size_t length, /* The length of the buffer */ loff_t *offset) /* Our offset in the file */
字符设备驱动程序实验报告

操作系统课程设计报告字符驱动设备程序一、概述1.1课程设计目的设备驱动充当了硬件和应用软件之间的纽带,它使得应用软件只需要调用软件的应用编程接口(API)就可以让硬件去完成要求的工作,在有操作系统的情况下,必须按照相应的架构设计驱动,才能将驱动良好的整合入操作系统的内核。
通过这次课程设计可以了解linux的模块机制,懂得如何加载模块和卸载模块,进一步熟悉模块的相关操作。
加深对驱动程序定义和设计的了解,了解linux驱动的编写过程。
1.2 课程设计内容与要求(1)设计Windows XP或者Linux操作系统下的设备驱动程序;(2)设备类型可以是字符设备、块设备或者网络设备;(3)设备可以是虚拟的也可以是实际设备;1.3设计步骤1)file_operations结构体设计2)模块初始化、模块卸载函数实现3)读写函数的实现4)测试程序编写5)驱动程序编译和加载6)驱动程序测试二、基本概念和原理Linux系统从各异的设备中提取了共性的特征,将设备分为三类:字符设备、块设备和网络设备。
内核针对每一类设备都提供了对应的驱动模型框架,包括基本的内核设施和文件接口。
系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。
设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。
设备驱动程序是内核的一部分,它完成以下的功能:1、对设备初始化和释放;2、把数据从内核传送到硬件和从硬件读取数据;3、读取应用程序传送给设备文件的数据和回送应用程序请求的数据;4、检测和处理设备出现的错误。
字符设备驱动程序:控制长短不一致字符列,应用程序直接呼叫的、没有缓存的设备驱动程序。
字符设备驱动程序所提供的功能是以设备文件的形式提供给用户空间程序使用,应用程序中使用open()、close()、read()、write()等文件处理函数,并且以普通文件方式处理设备文件,从而控制硬件。
操作系统课程虚拟字符设备驱动作业

操作系统课程:Linux字符设备驱动作业作业要求:1.为提供的虚拟字符设备编写驱动程序2.编写测试驱动的程序并测试通过提供的虚拟字符设备(softdev.tgz):–虚拟设备文件:softdev.c–功能:小写转大写•softdev_send()•softdev_recv()•softdev_ioctl()–主要文件:•Makefile•softdev.c•softdev.h–编译加载设备方法•make•insmod softdev.ko检查标准:•测试标准–在/proc/devices中能看到该设备名:“upper”,主设备号:117,设备类型:字符设备–可以对该设备进行读写。
作业的内容包括对设备的读写程序。
可以用该程序对设备进行测试–设置设备做大写转换或者不做大写转换。
缺省状态下做小写到大写转换,可以设置为不做转换–该设备驱动用softdev设备的softdev_send和softdev_recv做发送和接受–使用模块(module)方式加载•测试程序具体要求–写设备程序:dwrite,一次写一个字符串,写完退出•dwrite <device name> <string>–读设备程序:dread,循环读取设备接收到数据,并显示•dread <device name>–设置设备程序:dioctl,设置设备工作方式,0:不做大写转换,1:做大写转换。
缺省工作方式为1•dioctl <device name> <digit mode>•作业提交的文件:–Makefile–upperdev.c–dread.c–dwrite.c–dioctl.c作业完成代码(虚拟设备文件和驱动程序文件、测试驱动程序文件网络地址见最后):1.MakeFile文件# Makefile for upper# Author:Yuguangxi# Detail Information:according to Readme file in parent directory. KVER := $(shell uname -r)KSRC := /lib/modules/$(KVER)/build#MODDESTDIR := /lib/modules/$(KVER)/kernel/drivers/char/upperdrv obj-m := upper.o#EXTRA_CFLAGS +=/home/yuguangxi/softdev/Module.symversall: modulesmodules:$(MAKE) -C $(KSRC) M=$(shell pwd) modulesclean:rm -f *.o *.ko2.upper.h文件:#ifndef _UPPERDEVICE_HEADER#define _UPPERDEVICE_HEADER#define UPPER_MAJOR 117#define CHRDEV "upper"#define UPPERIOCTL_DISABLE 0#define UPPERIOCTL_ENABLE 1#endif3.Uppder.c文件#include <linux/module.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/device.h>#include <linux/ioctl.h>#include <linux/parport.h>#include <linux/ctype.h>#include <linux/poll.h>#include <linux/slab.h>#include <linux/major.h>#include <linux/cdev.h>#include <linux/mutex.h>#include <linux/uaccess.h>#include <linux/fs.h>#include <linux/wait.h>#include <linux/semaphore.h>#include "upper.h"//softdev functions declareextern int softdev_send(unsigned char *buff, int len);extern int softdev_recv(unsigned char **p);extern int softdev_ioctl(int cmd);//upper device functions declarestatic int upper_open( struct inode *inode, struct file *fp );static int upper_release( struct inode *inode, struct file *fp );static ssize_t upper_read( struct file *fp, char __user *buf, size_t count,loff_t*upperpos);static ssize_t upper_write( struct file *fp, const char __user *buf, size_t count,loff_t *upperpos );static long upper_ioctl( struct file *fp,unsigned int cmd,unsigned long arg); static void upper_setup_cdev( struct cdev *dev, int minor, structfile_operations *fops );static struct cdev upper;static struct file_operations upper_ops={.owner=THIS_MODULE,.open=upper_open,.read=upper_read,.write=upper_write,.release=upper_release,.unlocked_ioctl=upper_ioctl,};/* Open the device */static int upper_open( struct inode *inode, struct file *fp ){printk( KERN_NOTICE"upper device open!\n" );return 0;}/* Close _device */static int upper_release( struct inode *inode, struct file *fp ){printk( KERN_NOTICE"upper device close!\n" );return 0;}/* user read from device*/static ssize_t upper_read( struct file *fp, char __user *buf, size_t count,loff_t*upperpos){unsigned char *p=NULL;unsigned char **pp=&p;//call softdev_recv to finish readif(softdev_recv(pp)==0){printk(KERN_NOTICE"Upper read error!\n");return -1;}printk(KERN_NOTICE"Upper_write:%d\n",copy_to_user(buf,p,count));return count;}/* write to device */static ssize_t upper_write( struct file *fp, const char __user *buf_write, size_t count, loff_t*upperpos ){unsigned char send_buff[1512];printk(KERN_NOTICE"Upper_write:%lu\n",copy_from_user(send_buff,buf_write,count));if(softdev_send(send_buff, count) <= 0){printk(KERN_NOTICE"upper_write error!\n");return -1;}return count;}static long upper_ioctl( struct file *fp,unsigned int cmd,unsigned long arg){int cmd_nr=UPPERIOCTL_ENABLE;cmd_nr=_IOC_NR(cmd);switch(cmd_nr){case UPPERIOCTL_DISABLE:softdev_ioctl(0);break;default: softdev_ioctl(1);break;}}//upper device initializestatic int upper_init(void){if (register_chrdev (UPPER_MAJOR, CHRDEV, &upper_ops)){printk (KERN_WARNING CHRDEV ": unable to get major %d\n",UPPER_MAJOR);return -1;}//call upper_setup_cdev to really do initializationupper_setup_cdev(&upper, 0 , &upper_ops );}/* Exit routine */static void upper_exit(void){/* remove the cdev from kernel */cdev_del(&upper );/* release the device numble alloced earlier */unregister_chrdev(UPPER_MAJOR,CHRDEV);printk( KERN_NOTICE"upper exit. major:%d,minor %d\n",UPPER_MAJOR,0 ); }/* set up the cdev stucture for a device */static void upper_setup_cdev( struct cdev *dev, int minor, structfile_operations *fops ){int err;int devno = MKDEV( UPPER_MAJOR, minor );/* initialize the cdev struct */cdev_init( dev,fops );dev->owner = THIS_MODULE;err = cdev_add( dev, devno, 1 ); /* register the cdev in the kernel */if(err)printk( KERN_NOTICE"Error %d adding uppero%d\n",err ,minor );}/* register the init and exit routine of the module */ module_init( upper_init );module_exit( upper_exit );MODULE_AUTHOR( "Yuguangxi" );MODULE_LICENSE( "Dual BSD/GPL" );4.dwrite.c#include <stdio.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>int main(int argc,char *argv[]){int fp=open(argv[1],O_WRONLY);if(fp==-1)printf("open file failed!\n");if(write(fp,argv[2],sizeof(argv[2]))==-1)printf("Write error!\n");close(fp);}5.dread.c#include <stdio.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>int main(int argc,char *argv[]){int fp=open(argv[1],O_RDONLY);char buf[1024];while(1){//if(read(fp,buf,sizeof(buf))==-1)// printf("Read error!\n");//elseif(read(fp,buf,sizeof(buf))==-1)buf[0]='\0';if(buf[0]!='\0')printf("%s\n",buf);}close(fp);}6.dioctl.c#include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <fcntl.h>#include <unistd.h>#define UPPERIOCTL_DISABLE 0#define UPPERIOCTL_ENABLE 1int main(int argc,char *argv[]){int fp=open(argv[1],O_RDONLY);int mode;if(argc==3)mode=atoi(argv[2]);elsemode=1;//default option:enable capital transferswitch(mode){case 0:ioctl(fp,UPPERIOCTL_DISABLE);break;case 1:ioctl(fp,UPPERIOCTL_ENABLE);break;default:printf("Digital Mode Invalid!\n");//enable capital transferioctl(fp,UPPERIOCTL_ENABLE);break;}close(fp);}分享地址为/s/1sjJf6w9,仅供参考。
实验二:字符设备驱动实验

实验二:字符设备驱动实验一、实验目的通过本实验的学习,了解Linux操作系统中的字符设备驱动程序结构,并能编写简单的字符设备的驱动程序以及对所编写的设备驱动程序进行测试,最终了解Linux操作系统如何管理字符设备。
二、准备知识字符设备驱动程序主要包括初始化字符设备、字符设备的I/O调用和中断服务程序。
在字符设备驱动程序的file_operations结构中,需要定义字符设备的基本入口点。
open()函数;release()函数read()函数write()函数ioctl()函数select()函数。
另外,注册字符设备驱动程序的函数为register_chrdev()。
register_chrdev() 原型如下:int register_chrdev(unsigned int major, //主设备号const char *name, //设备名称struct file_operations *ops); //指向设备操作函数指针其中major是设备驱动程序向系统申请的主设备号。
如果major为0,则系统为该驱动程序动态分配一个空闲的主设备号。
name是设备名称,ops是指向设备操作函数的指针。
注销字符设备驱动程序的函数是unregister_chrdev(),原型如下:int unregister_chrdev(unsigned int major,const char *name);字符设备注册后,必须在文件系统中为其创建一个设备文件。
该设备文件可以在/dev目录中创建,每个设备文件代表一个具体的设备。
使用mknod命令来创建设备文件。
创建设备文件时需要使用设备的主设备号和从设备号作为参数。
阅读教材相关章节知识,了解字符设备的驱动程序结构。
三、实验内容根据教材提供的实例。
编写一个简单的字符设备驱动程序。
要求该字符设备包括open()、write()、read()、ioctl()和release()五个基本操作,并编写一个测试程序来测试所编写的字符设备驱动程序。
字符设备驱动实验报告(3篇)

第1篇一、实验背景与目的随着计算机技术的飞速发展,操作系统对硬件设备的支持越来越丰富。
设备驱动程序作为操作系统与硬件之间的桥梁,扮演着至关重要的角色。
本实验旨在通过学习Linux字符设备驱动的开发,加深对设备驱动程序的理解,提高实践能力。
二、实验环境与工具1. 操作系统:Linux Ubuntu 20.042. 编程语言:C3. 开发工具:gcc、make4. 驱动框架:Linux内核三、实验内容本实验主要完成以下内容:1. 字符设备驱动程序的基本框架2. 字符设备的打开、读取、写入和关闭操作3. 字符设备驱动的注册与注销4. 字符设备驱动的用户空间交互四、实验步骤1. 创建设备文件首先,我们需要在`/dev`目录下创建一个名为`mychar`的字符设备文件。
可以使用以下命令:```bashmknod /dev/mychar c 123 0```其中,`123`是主设备号,`0`是次设备号。
2. 编写字符设备驱动程序创建一个名为`mychar.c`的文件,并编写以下代码:```cinclude <linux/module.h>include <linux/fs.h>include <linux/uaccess.h>static int major = 123; // 设备号static int device_open(struct inode inode, struct file filp);static int device_release(struct inode inode, struct file filp);static ssize_t device_read(struct file filp, char __user buf, size_t count, loff_t pos);static ssize_t device_write(struct file filp, const char __user buf, size_t count, loff_t pos);static struct file_operations fops = {.open = device_open,.release = device_release,.read = device_read,.write = device_write,};static int __init mychar_init(void) {major = register_chrdev(0, "mychar", &fops);if (major < 0) {printk(KERN_ALERT "mychar: can't get major number\n");return major;}printk(KERN_INFO "mychar: registered correctly with major number %d\n", major);return 0;}static void __exit mychar_exit(void) {unregister_chrdev(major, "mychar");printk(KERN_INFO "mychar: Goodbye from the LKM!\n");}static int device_open(struct inode inode, struct file filp) {printk(KERN_INFO "mychar: Device has been opened\n");return 0;}static int device_release(struct inode inode, struct file filp) {printk(KERN_INFO "mychar: Device has been closed\n");return 0;}static ssize_t device_read(struct file filp, char __user buf, size_t count, loff_t pos) {printk(KERN_INFO "mychar: Device has been read\n");return count;}static ssize_t device_write(struct file filp, const char __user buf, size_t count, loff_t pos) {printk(KERN_INFO "mychar: Device has been written\n"); return count;}module_init(mychar_init);module_exit(mychar_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("Your Name");MODULE_DESCRIPTION("A simple character device driver");```保存文件,并使用以下命令编译:```bashmake```3. 加载字符设备驱动程序将编译生成的`mychar.ko`文件加载到内核中:```bashinsmod mychar.ko```4. 测试字符设备驱动程序使用以下命令查看`/dev/mychar`设备文件:```bashls -l /dev/mychar```使用`cat`命令测试读取和写入操作:```bashcat /dev/mycharecho "Hello, world!" > /dev/mychar```观察系统日志,确认驱动程序的打开、读取、写入和关闭操作。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Linux系统驱动开发之字符设备虚拟设备实
验
本系列图文(教程)均以全志H3开发板为实验板设计,字符设备驱动开发是最基础的驱动开发。
其本质是按字节进行读写操作,读写数据是分先后顺序的。
(LED)、按键、I(IC)、SPI、(USB)等等都是字符设备,驱动加载成功以后会在“/dev”目录下生成相应的文件,应用程序通过对“/dev/xxx进行操作即可实现对(硬件)的控制”。
应用程序中的每一个系统调用,都在驱动程序中有相应的驱动函数,(Linux)内核文件中存在着一个内核驱动操作函数集合,以结构体file_opera(ti)ons展现。
static inline int register_chrdev(unsigned int maj(or), const char *name,const struct file_operations *fops)static inline void unregister_chrdev(unsigned int major, const char *name) 最后我们需要在驱动中加入LICENSE 信息和信息,其中LICENSE 是必须添加的,否则的话编译的时候会报错,信息非必须。
添加函数为:
MODULE_LICENSE()MODULE_AUTHOR() Linux如何判断当下的设备就是程序想要调用的那一个呢,通过设备号对设备进行唯一匹配。
有动态和静态两种分配方式,我们先讲解旧的驱动设备注册方式(静态),也就是使用register_chrdev函数注册设备。
其三个参数分
别是主设备号(手动分配),设备名称(字符串),函数集合指针结构体。
主设备号的可选范围是0-4095,所以使用之前先查看开发板的Linux系统还有哪些设备号没有用,使用命令cat /proc/devices查看。
最后就是完整的编写驱动和应用程序,驱动程序完成设备打开,读写操作,使用一个虚拟读写设备做一个简单的例子。
借助copy_to_user(将内核态数据复制到用户态)和printk函数(内核态)完成(模拟)。
共分以下几步
•编写驱动程序(对printk的解释内核态,设备注册等)
•编写App程序(open等函数)
•编译驱动程序成.ko 测试(编写Makefile文件)
•编译App
•(下载)到(TF)的rootfs分区下
•找到相应文件夹下加载模块insmod **.ko
•查看系统中的所有设备cat /proc/devices
•创建设备节点文件mknod /dev/chrdevbase c 200 0 然后再执行上一步查看设备是否多了chrdevbase
c表示字符设备,200是主设备号,0是次设备号
•如果App要读写chrdevbase设备,直接操作/dev/chrdevbase 就可以
读操作测试./chrdevbaseApp /dev/chrdevbase 1。