您的位置:首页 > 运维架构 > Linux

Linux字符设备驱动——初体验

2016-05-18 23:05 549 查看
以下是一个非常简单的Linux字符设备驱动  *^_^*

【驱动程序myChrDrv.c】

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>

static int myChrDrv_open(struct inode *inod, struct file *fp)
{
printk(KERN_INFO "myChrDrv_open()\n");
return 0;
}

static int myChrDrv_close(struct inode *inod, struct file *fp)
{
printk(KERN_INFO "myChrDrv_close()\n");
return 0;
}

static struct file_operations fops = {
.open = myChrDrv_open,
.release = myChrDrv_close,
};

static int __init myChrDrv_init(void)
{
printk(KERN_INFO "myChrDrv_init()\n");
int ret;
// 创建并向内核注册字符设备simple_chrdev
ret = register_chrdev(250, "simple_chrdev", &fops);
return 0;
}

static void __exit myChrDrv_exit(void)
{
printk(KERN_INFO "myChrDrv_exit()\n");
unregister_chrdev(250, "simple_chrdev");
}

module_init(myChrDrv_init);
module_exit(myChrDrv_exit);

MODULE_LICENSE("Dual BSD/GPL");


【驱动程序Makefile】

obj-m += myChrDrv.o

#CROSS_COMPILE = /usr/local/arm/arm-2010.09/bin/arm-none-linux-gnueabi-
#CC = $(CROSS_COMPILE)gcc
#KDIR   := /home/walle/arm/arm_os/kernel/linux-3.10.10

KDIR := /lib/modules/`uname -r`/build

default:
$(MAKE) -C $(KDIR) M=`pwd` modules

clean:
$(MAKE) -C $(KDIR) M=`pwd` modules clean


【应用程序app.c】

#include <stdio.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
int fd;
fd = open("/dev/simple_chrdev", O_RDWR);

if(fd < 0){
printf("open /dev/simple_chrdev failed.\n");
return -1;
}
printf("open /dev/simple_chrdev successed.\n");

close(fd);
return 0;
}


执行命令 make,编译生成驱动模块 myChrDrv.ko。

执行命令 insmod myChrDrv.ko,加载驱动模块。

执行命令 lsmod,确认模块加载成功,输出如下:

Module                  Size  Used by
myChrDrv               12478  0


或执行命令 cat /proc/modules | grep myChrDrv,输出如下:

myChrDrv 12478 0 - Live 0xf8d28000 (O)


执行命令 dmesg | tail,查看模块初始化打印信息,输出如下:

[850978.514035] myChrDrv_init()


执行命令 gcc app.c -o app,编译生成应用程序 app。

执行命令 ./app,运行 app,出错:

open /dev/simple_chrdev failed.


  虽然驱动程序初始化函数中有“register_chrdev(250, “simple_chrdev”, &fops);”,函数 register_chrdev 的作用是申请主设备号250、绑定操作相关函数 fops、向内核注册设备名为 simple_chrdev 的设备。显然此时系统中并不存在 /dev/simple_chrdev,因此需要执行命令“mknod /dev/simple_chrdev c 250 0”手动创建该设备节点。

  mknod 的格式是:mknod [OPTION]… NAME TYPE [MAJOR MINOR]。命令中的“c”表示字符设备;“250”是主设备号,与驱动程序中手动申请的主设备号一致;“0”是次设备号,这里也可以不设为0,只需要主设备号对应得上就行,因为主设备号指定的是驱动,次设备号指定的是具体设备。

  另外文件“/dev/simple_chrdev”要与 app.c 中 open 函数打开的文件一致,所以如果 open 指定的文件是“hello”,mknod 命令创建“hello”即可。这里之所以用“/dev/simple_chrdev”主要是为了让它看起来像一个设备。

  

  OK,我们执行命令 ls -l /dev/simple_chrdev,确认设备节点创建成功,输出如下:

crw-r--r-- 1 root root 250, 0  5月 18 22:34 /dev/simple_chrdev


再次执行命令 ./app,运行 app,成功:

open /dev/simple_chrdev successed.


执行命令 dmesg | tail,查看驱动程序打印信息,输出如下:

[854089.294682] myChrDrv_open()
[854089.294855] myChrDrv_close()


可以看到,应用程序 app 的 open 和 close 函数最终调用了驱动程序 myChrDrv 的 open 和 release 函数。

执行命令 rmmod myChrDrv,卸载 myChrDrv 驱动。

执行命令 dmesg | tail,查看驱动程序打印信息,输出如下:

[854555.685634] myChrDrv_exit()


执行命令 rm /dev/simple_chrdev,移除设备节点。

Linux字符设备驱动的初体验完毕  *>_<*
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: