第一个驱动程序(在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/
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号