文章目录
模块代码(1)register_chrdev字符注册函数的作用是什么?(2)怎么查看已经注册好的驱动?(3)驱动的设备号本质的作用是什么?(4)有了驱动,那怎么调用它的函数?(5)字符设备文件怎么与注册了的驱动关联上?
应用程序代码Makefile编写
实验现象
先奉上代码
模块代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#define MYMAJOR 0
#define NAME "MyModule"
int major
;
static int module_open(struct inode
*inode
, struct file
*file
)
{
printk("module_open\n");
return 0;
}
static ssize_t
module_write(struct file
*file
,
const char __user
*user_buf
,
size_t count
, loff_t
*ppos
)
{
printk("module_write\n");
return 0;
}
static ssize_t
module_read(struct file
*file
, char __user
*buf
, size_t size
, loff_t
*ppos
)
{
printk("module_read\n");
return 0;
}
static int module_release(struct inode
*inode
, struct file
*file
)
{
printk("module_release\n");
return 0;
}
static const struct file_operations fops
= {
.open
= module_open
,
.write
= module_write
,
.read
= module_read
,
.release
= module_release
,
.owner
= THIS_MODULE
,
};
static int __init
module_test(void)
{
printk(KERN_DEBUG
"install module_test");
major
= register_chrdev(MYMAJOR
, NAME
, &fops
);
if (major
< 0)
{
printk(KERN_ERR
"register_chrdev failed\n");
return -EINVAL
;
}
printk("module_test major: %d\n",major
);
}
static void __exit
module_ex(void)
{
unregister_chrdev(major
, NAME
);
printk(KERN_DEBUG
"uninstall module_test");
}
module_init(module_test
);
module_exit(module_ex
);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Zhou");
(1)register_chrdev字符注册函数的作用是什么?
首先,我们来看看它需要什么参数。第一个参数输入的主设备号,第二参数传入你的驱动名字,第三个参数传入对应的file_operations结构体。
reguster_chrdev成功调用后,驱动就被注册到内核的驱动表当中,本质上是将驱动的file_operations结构体注册到内核的驱动表中。
register_chrdev默认的次设备号是 0. cd = __register_chrdev_region(major, 0, 256, name);这个是内部其中的一行代码。第一个传入注射比号,第二个传入次设备号。
register_chrdev_region函数,可以区分设备的主次设备号。
有了注册,应当也有注销驱动。unregister_chrdev
(2)怎么查看已经注册好的驱动?
输入命令 cat /proc/devices 可以查看。
(3)驱动的设备号本质的作用是什么?
从上图我们可以看到,最左边的一列就是主设备号,从低到高往下排列。主设备号这相当于这一列表的一个索引,最多能存放256个。在调用register_chrdev时,我传入了MYMAJOR,即输入 0,表示内核自动分配一个设备号,它采取的策略是从后往前寻找一个空闲的位置。
有了驱动的设备号,那么,字符设备就能很轻易地找到它对应的驱动,只要设备号对上了。
(4)有了驱动,那怎么调用它的函数?
首先,我们要明确一条的路线: 在应用程序中,操作字符设备文件(open、read、write) --> 字符设备文件的操作已经被重映射到对应的驱动,最终调用的file_operations结构体中的open、read、write。
(5)字符设备文件怎么与注册了的驱动关联上?
在 /dev 的文件夹中,mknod MyModule c 248 0新建字符类型的文件,248是主设备号,0是次设备号。这样,就跟驱动关联上。设备号与次设备号必须跟驱动的对应上。
应用程序代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#define DEV_DIR "/dev/MyModule"
int main(void)
{
int fd
;
char buf
[10];
fd
= open(DEV_DIR
, O_RDWR
);
if (fd
< 0)
{
perror("open failed!\n");
}
write(fd
, "12345", 5);
read(fd
, (char*)buf
, 10);
close(fd
);
return 0;
}
Makefile编写
obj
-m
= module_test
.o
KER_DIR
= /home
/iTOP4421
/iTop4412_Kernel_3
.0 # 开发板Linux内核的位置
PWD
= $
(shell pwd
)
all
:
make
-C $
(KER_DIR
) M
=$
(PWD
) modules
arm
-linux
-gnueabi
-gcc
-o app app
.c
.PHONY
:clean
clean
:
make
-C $
(KER_DIR
) M
=$
(PWD
) clean
实验现象