今天完成我的第一个字符驱动程序,这个程序什么都不做,只是用来尝试字符驱动的开发过程和了解驱动的开发框架,以此来开启我的Linux驱动程序开发之旅。感谢夏老师和网友萍,因为刚开始编译有点问题一直卡在那里,是他们帮助完成这个例子。
现在记录过程如下
1.编写字符驱动:testdriver.c
/*2008-06-22*/
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
MODULE_******("Dual BSD/GPL");
int testdriver_major=200;
/***************************************OPEN***************************************/
static int testdriver_open(struct inode *inode,struct file *file)
{
printk("\nIt's in testdriver_open fuction!!!---in the testdriver.ko!!!\n");
//MOD_INC_USE_COUNT;
return 0;
}
/***************************************READ***************************************/
static int testdriver_read(struct inode *node,struct file *file,char *buf,int count)
{
printk("\nIt's in testdriver_read fuction!!!---in the testdriver.ko!!!\n");
return count;
}
/***************************************WRITE***************************************/
static int testdriver_write(struct inode *inode,struct file *file,const char *buf,int count)
{
printk("\nIt's in testdriver_write fuction!!!---in the testdriver.ko!!!\n");
return count;
}
/***************************************RELEASE***************************************/
static void testdriver_release(struct inode *inode,struct file *file)
{
printk("\nIt's in testdriver_release fuction!!!---in the testdriver.ko!!!\n");
//MOD_DEC_USE_COUNT;
}
struct file_operations testdriver_fops=
{
.read=testdriver_read,
.write=testdriver_write,
.open=testdriver_open,
.release=testdriver_release,
};
static int testdriver_init(void)
{
printk("Hello ,it's a testdriver!!!---in the testdriver.ko!!!\n");
int ret;
ret=register_chrdev(testdriver_major,"testdriver",&testdriver_fops);//注册设备
if(ret<0)
{
printk("init_module failed with %d---in the testdriver.ko!!!\n",ret);
return ret;
}
else
{
printk("init_module testdriver success!!!---in the testdriver.ko!!!\n");
}
return ret;
}
static void testdriver_exit(void)
{
unregister_chrdev(testdriver_major,"testdriver");
printk("Goodbye,testdriver!!!---in the testdriver.ko!!!\n");
}
module_init(testdriver_init);
module_exit(testdriver_exit);
编写测试程序:test.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#define DEVICE_NAME "/dev/testdriver"
int main(void)
{
int fd;
int ret;
char *i;
printf("\nstart testdriver test---in the test!!!\n\n");
fd=open(DEVICE_NAME,O_RDWR);
if(fd==-1)
{
printf("open device %s error---in the test!!!\n",DEVICE_NAME);
}
else
{
printf("open device %s success!!!---in the test!!!\n",DEVICE_NAME);
ret=close(fd);
printf("ret=%d\n",ret);
printf("close testdriver test!!!---in the test!!!\n");
}
return 0;
}
3.编写Makefile文件
# Makefile2.4
ifneq ($(KERNELRELEASE),)
obj-m := testdriver.o
else
PWD := $(shell pwd)
# where the kernel sources are located
//KERNEL_DIR :=/usr/local/src/gec2410-linux-2.6.8.1/
KERNEL_DIR := /yl2410/linux-2.6.8.1-zzm/
all:
#$(MAKE) -C $(KDIR) M=$(PWD)
cd $(KERNEL_DIR); make SUBDIRS=$(PWD) modules
clean:
rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions
endif
4.编译驱动程序和测试程序:
虚拟机,进入驱动程序和测试程序目录,敲make编译驱动程序,其中生成testdriver.ko是我们的驱动模块。
用命令arm-linux-gcc -c test test.c,生成可执行文件test。
最后讲他们拷贝到我的NFS共享目录/tmp/nfs中。
4.启动开发板进入Linux,配置开发板IP,NFS挂载主机NFS共享目录/tmp/nfs到开发板/tmp/2410目录。(这里主机端配置NFS服务器不再详述)
开发板:10.10.207.93
ifconfig eth0 10.10.207.93 broadcast 10.10.10.207.254 netmask 255.255.255.0(然后虚拟机ping开发板:ping 10.10.207.93,ping通则网络连上。)
mkdir /tmp/1
mount -t nfs -o nolock 10.10.207.92:/tmp/nfs /tmp/2410nfs
4.进入开发板/tmp目录,加载驱动程序testdriver.ko。
并查看驱动加载与否:(主设备号为200,设备名为testdriver)

4.创建字符设备入口点,并查看创建结果:


5.执行测试程序,查看驱动程序正确与否。

可以看到驱动程序中,open函数和release函数都正确调用。
值得注意的是:
1.这里测试程序只考虑了open、release函数。也应该考虑其他函数的执行情况。这个地方没考虑到。
2.另外,在程序执行过程中,应用程序的打印信息都还未来得及打印,驱动程序(内核空间执行的)极已执行,应用程序的open函数,。从图中可以看出。