Linux内核开发——自定义字符设备
Posted -飞鹤-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux内核开发——自定义字符设备相关的知识,希望对你有一定的参考价值。
1. 前言
Linux内核的驱动入门比较简单,只需要注册module_init和module_exit两个函数即可以完成最简单的驱动编译。然后就可以编译,接着将驱动文件载入系统就自动执行。
2. 普通驱动
2.1. 驱动代码
新建hello.c文件,内容如下:
#include<linux/kernel.h>
#include<linux/init.h>
#include<linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Mike");
static int __init hello_init(void)
printk("Hello Mike!\\n") ;
return 0;
static void __exit hello_exit(void)
printk("Exit Mike!\\n");
module_init(hello_init);
module_exit(hello_exit);
2.2. 编译
内核编译方法:
$(MAKE) -C ( K D I R ) M = (KDIR) M= (KDIR)M=(PWD) modules
参照内核编译方法编写一个Makefile:
# obj-m表示后面的内容编译为ko文件,如果有多个文件按空格分隔开添加
obj-m:=hello.o
PWD:=$(shell pwd)
KDIR=/lib/modules/$(shell uname -r)/build
# 下面利用makefile的隐式规则编译hello.o的同名hello.c文件,生链接生成ko文件
all :
make -C $(KDIR) M=$(PWD) modules
clean :
make -C $(KDIR) M=$(PWD) clean
2.3. 编译载入
sudo make
sudo insmod helloKo.ko
sudo rmmod helloKo
通过dmesg可以看到驱动的载入及退出。
3. 字符设备
3.1. 字符设备驱动
字符设备主要通过register_chrdev来注册,并实现file_operations中的几个基本的接口即可。
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#define MAJOR_NUM 250
#define DEVICE_NAME "hello"
int DriverOpen(struct inode *pslINode, struct file *pslFileStruct)
printk( "hello open.\\n" );
return(0);
ssize_t DriverWrite( struct file *pslFileStruct, const char __user *pBuffer, size_t nCount, loff_t *pOffset )
printk( "hello write.\\n" );
return(0);
long DriverIOControl( struct file *pslFileStruct, unsigned int uiCmd, unsigned long ulArg )
printk(" hello ioctl.\\n" );
return(0);
struct file_operations hello_flops =
.owner = THIS_MODULE,
.open = DriverOpen,
.write = DriverWrite,
.unlocked_ioctl = DriverIOControl
;
static int __init hello_init( void )
int ret;
ret = register_chrdev( MAJOR_NUM, DEVICE_NAME, &hello_flops );
if ( ret < 0 )
printk(" can't register major number.\\n" );
return(ret);
printk( " initialized.\\n" );
return(0);
static void __exit hello_exit( void )
printk("exit .\\n" );
unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
module_init( hello_init );
module_exit( hello_exit );
MODULE_LICENSE( "GPL" );
MODULE_AUTHOR( "Mike" );
3.2. 编译安装
sudo make
sudo insmod helloKo.ko
使用lsmod命令查看安装的模块。
3.3. 生成设备文件
如果想访问某设备,则必须有对应的设备文件。驱动虽然已经载入到系统中,但是并没有对应的设备文件,这样应用程序就无法访问该驱动。Linux内核提供了mknod工具用来为驱动创建相应的设备文件。
mknod语法:
mknod DEVNAME b | c MAJOR MINOR
DEVNAME 为设备名,b|c则代码块设备或字符设备,后面则为主次版本号。
为驱动创建设备文件:
mknod /dev/hello c 250 0
执行上面的命令之后,就可以在dev目录看到hello文件,我们就可以正式访问这个字符设备了。
3.4. 测试
3.4.1. 代码
测试代码是用户态代码,主要是调用open打开驱动,并调用ioctl向驱动发起请求。编译main.cpp代码,如下:
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <stropts.h>
#include <string.h>
using namespace std;
int main( void )
int fd;
if ( (fd = open( "/dev/hello", O_RDWR ) ) < 0 )
cerr << strerror( errno ) << endl;
return(-1);
ioctl(fd, 1, 0);
close(fd);
return(0);
3.4.2. 编译运行
g++ main.cpp -o main
sudo ./main
查看dmesg结果:
以上是关于Linux内核开发——自定义字符设备的主要内容,如果未能解决你的问题,请参考以下文章