一、一个简单的驱动程序实例
led_drv.c 驱动文件:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#define DEVICE_MAJOR 111
#define DEVICE_NAME "led_drv"
int led_open(struct inode *inode, struct file *file)
{
printk(KERN_EMERG "led_drv_open.\n");
return 0;
}
int led_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
printk(KERN_EMERG "led_drv_write.\n");
return 0;
}
int led_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
printk(KERN_EMERG "led_drv_read.\n");
return 0;
}
static struct file_operations led_fopt = {
.open = led_open,
.write = led_write,
.read = led_read,
};
int __init led_init()
{
int ret;
ret = register_chrdev(DEVICE_MAJOR, DEVICE_NAME, &led_fopt); //注册驱动
if(ret<0)
{
printk(KERN_EMERG "can't register major number.\n");
return ret;
}
return 0;
}
void __exit led_exit()
{
unregister_chrdev(DEVICE_MAJOR, DEVICE_NAME); //卸载驱动
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
Makefile 文件:
obj-m += led_drv.o
KERN_DIR = /work/system/linux-2.6.22.6
all:
make -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order
使用 make 命令编译,生成 led_drv.ko, 拷贝 led_drv.ko 至 U 盘, 使用 mount /dev/sda1 /mnt/usb 命令加载 U 盘( mnt 下无 usb 目录需提前新建 )
加载模块 insmod led_drv.ko
卸载模块 rmmod led_drv
led_app 测试文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc, char **argv)
{
int fd;
int val = 1;
fd = open("/dev/syz", O_RDWR);
if(fd<0)
{
printf("can not open \n");
}
write(fd, &val, 4);
read(fd, &val, 4);
return 0;
}
使用 arm-linux-gcc -o led_app led_app.c 命令编译 ( 这里只有一个文件就不写 Makefile 了 ), 生成 led_app 拷贝至 U 盘, 并加载 U 盘
重新加载模块 insmod led_drv.ko
运行 ./led_app 发现控制台打印 can not open, 这是因为虽然有了设备驱动, 但是没有设备文件, 所以 open 失败, 因此要先创建设备文件
创建设备文件:
mknod /dev/syz c 111 0
运行 ./led_app, 控制台输出:
led_drv_open.
led_drv_write.
led_drv_read.