第一个驱动程序(在Ubuntu系统下运行)
一、构造内核源码树
# apt-cache search linux-source
# apt-get install linux-source-4.4.0(下载的源码在目录/usr/src下)
# 解压内核源码tar xjf .....
进入源码目录
# make oldconfig
# make
# make modules
make modules_install
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
ref:http://blog.chinaunix.net/uid-24782829-id-3211008.html
由于我主机本身内核版本就为4.4.0-21-generic,所以/lib/modules/4.4.0-21-generic/本身就存在,所以上述过程就不需要执行了。至此,构造内核源码树完成。
make时报错:
scripts/sign-file.c:23:30: fatal error: openssl/opensslv.h: 没有那个文件或目录 compilation terminated. scripts/Makefile.host:91: recipe for target 'scripts/sign-file' failed make[1]: *** [scripts/sign-file] Error 1 Makefile:566: recipe for target 'scripts
- 1
解决方法:ubuntu下缺少了如下的组件,安装一下即可
sudo apt-get install libssl-dev
- 1
二、在Linux下写驱动程序
源代码firstdrv.c:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
static int first_drv_open(struct inode *inode, struct file *file)
{
printk("first_drv_open\n");
return 0;
}
static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
printk("first_drv_write\n");
return 0;
}
static struct file_operations first_drv_fops = {
.owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
.open = first_drv_open,
.write = first_drv_write,
};
static int first_drv_init(void)
{
register_chrdev(246, "first_drv", &first_drv_fops); // 注册, 告诉内核
return 0;
}
static void first_drv_exit(void)
{
unregister_chrdev(246, "first_drv"); // 卸载
}
module_init(first_drv_init);
module_exit(first_drv_exit);
MODULE_LICENSE("GPL");
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
makefile:
obj-m:=firstdrv.o #注意.o文件名要和驱动程序文件名一致
CURRENT_PATH :=$(shell pwd)
LINUX_PATH :=/lib/modules/4.4.0-21-generic/build
all:
make -C $(LINUX_PATH) M=$(CURRENT_PATH) modules
clean:
make -C $(LINUX_PATH) M=$(CURRENT_PATH) clean
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
# make 编译模块
# insmod firstdrv.ko
#lsmod
#cat /proc/devices
- 1
- 2
- 3
- 4
测试程序firstdrvtest.c:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
int fd;
int val=1;
fd=open("/dev/xyz",O_RDWR);
if(fd<0)
printf("can't open\n");
write(fd,&val,4);
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
# mknod /dev/xyz c 246 0 创建设备节点
# ./firstdrvtest 执行测试程序
- 1
- 2
2017/9/15目前的情况是firstdrv.c可以正常加载(insmod)到/proc/devices,lsmod命令也能够看到该模块,但是给/dev/xyz创建节点后,在执行firstdrvtest测试时,无法打开该文件。
2017/9/18切换成root用户执行./firstdrvtest可执行文件,文件可以打开,但没有按照模块中open和write函数指定的方式打印信息,打印信息只可以在日志中查看。查了原因,是因为printk函数运行在内核态,如果要让它显示到虚拟终端上,还要加上其他的配置,如果不更改printk函数的显示等级,只能用dmesg命令查看输出信息,我又花了点时间折腾了下修改printk的输出日志等级,但是不知道是哪里操作不对,也没有实现理想的效果,暂且把这个问题搁下,接下来学习如何实现设备模块自动设置设备号和设备节点先。
from: https://codeleading.com/article/62054156384/