1、字符设备驱动编写步骤
2、更简单的注册
static int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops)
static void unregister_chrdev(unsigned int major, const char *name)
3、编写实例:
驱动函数
#include <linux/hdreg.h>
#include <linux/blkdev.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/skbuff.h>
#include <linux/export.h>
#include <linux/module.h>
unsigned int major=237;
const char * name = "zheng";
int hello_open (struct inode *inode, struct file *file)
{
printk("hello_open()\n");
return 0;
}
int hello_release (struct inode *inode, struct file *file)
{
printk("hello_release()\n");
return 0;
}
struct file_operations fops = {
.open = hello_open,
.release = hello_release,
};
static int hello_init(void)
{
int ret;
printk("hello_init()\n");
ret = register_chrdev(major, name, &fops);
if (ret < 0){
printk("register_chrdev fail!\n");
return ret;
}
return 0;
}
static void hello_exit(void)
{
printk("hello_exit()\n");
unregister_chrdev(major, name);
return;
}
MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit);
应用层测试程序
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int fd;
fd = open("/dev/test", O_RDWR);
if (fd < 0)
{
perror("");
return 0;
}
sleep(30);
close(fd);
return 0;
}
4、注:设备号、设备节点、驱动,每个得搞清楚什么意思
Linux下的设备通常分为三类,字符设备,块设备和网络设备。
设备驱动程序也分为对应的三类:字符设备驱动程序、块设备驱动程序和网络设备驱动程序。
常见的字符设备有鼠标、键盘、串口、控制台等。
常见的块设备有各种硬盘、flash磁盘、RAM磁盘等。
在Linux里一个网络设备也可以叫做一个网络接口,如eth0,应用程序是通过Socket而不是设备节点来访问网络设备,在系统里根本就不存在网络设备节点。网络接口没有像字符设备和块设备一样的设备号,只有一个唯一的名字,如eth0、eth1等,而这个名字也不需要与设备文件节点对应
编写一个驱动文件的时候生成一个name1.ko文件,这个name1就是驱动名,使用insmod name1.ko指令之后,用lsmod能看见一个名为name1的驱动
在调用了alloc_chrdev_region函数或register_chrdev_region函数时传入的最后一个参数为设备名,如果传入的为name2,则表示该设备名为name2,使用cat /proc/devices指令可以看到该设备名
使用mknod指令指定的文件名为设备文件名,该名字为使用open函数时打开的文件
设备节点被创建在/dev下,是连接内核与用户层的枢纽,就是设备是接到对应哪种接口的哪个ID 上。 相当于硬盘的inode一样的东西,记录了硬件设备的位置和信息。
在Linux中,所有设备都以文件的形式存放在/dev目录下,都是通过文件的方式进行访问,设备节点是Linux内核对设备的抽象,一个设备节点就是一个文件。应用程序通过一组标准化的调用执行访问设备,这些调用独立于任何特定的驱动程序。而驱动程序负责将这些标准调用映射到实际硬件的特有操作。
设备节点,驱动,硬件设备是如何关联到一起的呢?
这是通过设备号实现的,包括主设备号和次设备号。当我们创建一个设备节点时需要指定主设备号和次设备号。应用程序通过名称访问设备,而设备号指定了对应的驱动程序和对应的设备。主设备号标识设备对应的驱动程序,次设备号由内核使用,用于确定设备节点所指设备。
主设备号:驱动程序在初始化时,会注册它的驱动及对应主设备号到系统中,这样当应用程序访问设备节点时,系统就知道它所访问的驱动程序了。你可以通过/proc/devices文件来查看系统设备的主设备号。
次设备号:驱动程序遍历设备时,每发现一个它能驱动的设备,就创建一个设备对象,并为其分配一个次设备号以区分不同的设备。这样当应用程序访问设备节点时驱动程序就可以根据次设备号知道它说访问的设备了。
设备节点(设备文件):Linux中设备节点是通过“mknod”命令来创建的。一个设备节点其实就是一个文件,Linux中称为设备文件。有一点必要说明的是,在Linux中,所有的设备访问都是通过文件的方式,一般的数据文件程序普通文件,设备节点称为设备文件。
设备驱动:设备驱动程序(device driver),简称驱动程序(driver),是一个允许高级(High level)计算机软件(computer software)与硬件(hardware)交互的程序,这种程序建立了一个硬件与硬件,或硬件与软件沟通的界面,经由主板上的总线(bus)或其它沟通子系统(subsystem)与硬件形成连接的机制,这样的机制使得硬件设备(device)上的数据交换成为可能。想象平时我们说的写驱动,例如点led灯的驱动,就是简单的io操作。