前言:linux
本文将结合简单的驱动代码,讲述编写LINUX下驱动代码流程。所使用的平台是Ubantu14.。shell
本文讲述流程是:先放代码,编译生成驱动,安装卸载驱动。这个流程走完后再讲解驱动代码。bash
驱动测试代码(test.c):app
#include <asm/siginfo.h> #include <linux/rcupdate.h> #include <linux/version.h> #include <linux/slab.h> #include <linux/kobject.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/delay.h> #include <linux/dma-mapping.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/jiffies.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/uaccess.h> #include <linux/sched.h> #include <linux/device.h> /* 该驱动支持PCIE设备数量 */ #define CM_PCIE_MAX_MINORS (3) /* 该驱动的名称 */ #define CM_PCIE_DRIVER_NAME "cm_cpie" /* 配置信息 */ #define CM_ALTERA_ARRIA10_PCI_ID (0xe003) #define CM_ALTERA_ARRIA10_PCI_VID (0x1172) /* 逻辑类指针 */ static struct class *g_cmpcie_class = NULL; /* 主设备号 */ static int g_cmpcie_major = 0; /* 设备标记位 */ static unsigned char g_cmpcie_devices[CM_PCIE_MAX_MINORS]; /* 设备配置信息 */ static struct pci_device_id cmpcie_ids[] = { { PCI_DEVICE(CM_ALTERA_ARRIA10_PCI_VID, CM_ALTERA_ARRIA10_PCI_ID) }, { 0 } }; /* PCI-E设备插入内核时调用的函数 */ static int probe(struct pci_dev *dev, const struct pci_device_id *id) { printk("@INFO hava a pcie driver inster\n"); return 0; } /* PCI-E设备拔出内核调用的函数 */ static void remove(struct pci_dev *dev) { printk("@INFO hava a pcie driver remove\n"); } /* PCI-E驱动实例 */ static struct pci_driver g_cmpcie_driver = { .name = CM_PCIE_DRIVER_NAME, //驱动程序名称 .id_table = cmpcie_ids, //配置信息 .probe = probe, //PCI-E设备插入内核时调用的函数 .remove = remove, //PCI-E设备拔出内核时调用的函数 }; /* 驱动初始化函数 */ static int pcie_driver_init(void) { int i = 0, ret = 0; dev_t dev; printk("@INFO driver init\n"); /* 初始化设备标记位 */ for(i = 0; i < CM_PCIE_MAX_MINORS; i++) { g_cmpcie_devices[i] = 0; } /* 申请设备号 */ ret = alloc_chrdev_region(&dev, 0, CM_PCIE_MAX_MINORS, CM_PCIE_DRIVER_NAME); if(ret) { printk("apply for dev fail\n"); } else { printk("apply for dev success @dev %d\n", dev); } g_cmpcie_major = MAJOR(dev); /* 申请逻辑类指针 */ g_cmpcie_class = class_create(THIS_MODULE, CM_PCIE_DRIVER_NAME); if( IS_ERR(g_cmpcie_class) ) { printk("apply for class fail\n"); } else { printk("apply for class success\n"); } /* 在PCI-E总线上申请驱动 */ ret = pci_register_driver(&g_cmpcie_driver); if(ret) { printk("apply for driver fail"); } else { printk("apply for driver success"); } return 0; } /* 驱动销毁函数 */ static void pcie_driver_exit(void) { printk("driver exit"); /* 释放驱动 */ pci_unregister_driver(&g_cmpcie_driver); /* 释放指针 */ class_destroy(g_cmpcie_class); /* 释放设备号 */ unregister_chrdev_region(MKDEV(g_cmpcie_major, 0), CM_PCIE_MAX_MINORS); } module_init(pcie_driver_init); module_exit(pcie_driver_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Wang jianbin"); MODULE_DESCRIPTION("This is a driver for PCIE");
同一目录下的Makefile文件函数
#you want produce module name obj-m := modules.o #module needed object file name modules-objs := test.o #environment needed to complie the module KDIR := /lib/modules/`uname -r`/build #loalce path PWD := $(shell pwd) #M is source file path all: make -C $(KDIR) M=$(PWD) modules clean: rm *.o *.ko *.order *.symvers *.mod.c
运行 make all测试
如图modules.ko即是驱动程序 ui
安装驱动命令:insmod modules.ko 指针
查看驱动信息命令:modinfo modules.kocode
分析驱动依赖性名:depend modules.koblog
卸载驱动命令:rmmod modules
查看内核输出信息:dmesg
查看全部驱动命令:lsmod
查看设备号命令 : cat /pro/devices