本文由xhz1234(徐洪志)编写,转载请注明出处。
在Linux中,字符设备驱动程序是最常见的一种设备驱动程序。
本文通过一个实际的例子来展示应用程序如何与字符设备驱动程序进行交互,先创建一个简单的字符设备驱动程序内核模块,然后insmod该模块到内核,之后通过mknod创建一个驱动对应的设备节点,最后编写一个应用程序,用应用程序调用前面设备驱动程序提供的服务。
字符设备驱动程序:cdev.c
#include
#include
#include
#include
#define CHR_DEV_NAME "my_chr_dev"
static struct cdev chr_dev;
static dev_t ndev;
static int chr_open(struct inode *nd, struct file *filp)
{
int major = MAJOR(nd->i_rdev);
int minor = MINOR(nd->i_rdev);
printk("chr_open,major=%d,minor=%d\n",major,minor);
return 0;
}
static ssize_t chr_read(struct file *f, char __user *u, size_t sz, loff_t *off)
{
printk("In the chr_read() function!\n");
return 0;
}
struct file_operations chr_ops =
{
.owner = THIS_MODULE,
.open = chr_open,
.read = chr_read,
};
static int demo_init(void)
{
int ret;
cdev_init(&chr_dev,&chr_ops);
ret = alloc_chrdev_region(&ndev, 0, 1, CHR_DEV_NAME);
if(ret < 0)
return ret;
printk("demo_init():major=%d,minor=%d\n", MAJOR(ndev),MINOR(ndev));
ret = cdev_add(&chr_dev, ndev, 1);
if(ret < 0)
return ret;
return 0;
}
static void demo_exit(void)
{
printk("Removing chr_dev module...\n");
cdev_del(&chr_dev);
unregister_chrdev_region(ndev, 1);
}
module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Xuhongzhi");
MODULE_DESCRIPTION("A char device driver as an example");
应用程序 usr_app.c
#include
#include
#include
#define CHR_DEV_NAME "/dev/my_chr_dev"
int main(void)
{
int ret;
char buf[32];
int fd = open(CHR_DEV_NAME, O_RDONLY|O_NDELAY);
if(fd < 0)
{
printf("open file %s failed\n", CHR_DEV_NAME);
return -1;
}
printf("Open file successfully!\n");
read(fd, buf, 32);
close(fd);
return 0;
}
将cdev.c编译出来的cdev.ko通过insmod工具加载到系统,dmesg查看有如下输出信息:
[ 975.177765] demo_init():major=247,minor=0
可知,alloc_chrdev_region函数给内核模块cdev.ko分配的设备号为(247,0)。据此,我们通过mknod在/dev目录下创建一个字符设备文件节点
#mknod /dev/my_chr_dev c 247 0
通过gcc编译usr_app.c,执行编译出来的可执行文件,查看dmesg,会有如下打印:
Aug 22 07:43:30 xhz-Rev-1-0 kernel: [ 1269.755804] chr_open,major=247,minor=0
Aug 22 07:43:30 xhz-Rev-1-0 kernel: [ 1269.755859] In the chr_read() function!
通过上述打印可知,用户程序使用了cdev.ko提供的chr_open和chr_read提供的功能。
虽然这个示例程序几乎未做任何事情,但是我们了解了应用程序如何成功调用设备驱动程序实现的功能。
源代码下载地址:http://huoxin.github.io/User-Application-And-Chrdev 包括(cdev.c usr_app.c Makefile)
参考:陈学松《深入Linux设备驱动程序内核机制》