下面一个文件是对 如何编写Linux设备驱动程序 (一)(二)(三)中提到的例子的一些注释,方便理解这个例子。也可以说是一个整合。
test.c:
#define __NO_VERSION__
#include <linux/modules.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <asm/segment.h>
unsigned int test_major = 0; //全局变量,主设备号
static int read_test(struct inode *node,struct file *file,char *buf,int count) //这个函数是为read调用准备的.当调用read时,read_test()被调用,它把用户的缓冲区全部写1
{
int left;
if (verify_area(VERIFY_WRITE,buf,count) == -EFAULT ) //验证buf是否可用
return -EFAULT;
for(left = count ; left > 0 ; left--)
{
__put_user(1,buf,1); //用于向用户传送数据,这是kernel提供的一个函数
buf++; //指针后移
}
return count; //返回buf的大小
}
static int write_tibet(struct inode *inode,struct file *file,const char *buf,int count)
{
return count;
}
static int open_tibet(struct inode *inode,struct file *file )
{
MOD_INC_USE_COUNT;
return 0;
}
static void release_tibet(struct inode *inode,struct file *file )
{
MOD_DEC_USE_COUNT;
}
struct file_operations test_fops = { //把系统调用和驱动程序关联起来。系统调用通过设备文件的主设备号找到相应的设备驱动程序,然后读取这个数据结构相应的函数指针,接着把控制权交给该函数
NULL,
read_test,
write_test,
NULL,
NULL,
NULL,
NULL,
open_test,
release_test, NULL,
NULL,
NULL,NULL
};
int init_module(void)
{
int result;
result = register_chrdev(0, "test", &test_fops); //向系统的字符设备表登记了一个字符设备,如果登记成功,返回设备的主设备号
if (result < 0) { //不成功,返回一个负值
printk(KERN_INFO "test: can't get major number\n");
return result;
}
if (test_major == 0) test_major = result;
return 0;
}
void cleanup_module(void)
{
unregister_chrdev(test_major, "test"); //把register_chrdev()中自动分配的字符设备号给注销掉
}
编译:
$ gcc -O2 -DMODULE -D__KERNEL__ -c test.c
得到文件test.o就是一个设备驱动程序
安装到系统:
$ insmod -f test.o
卸载:
$ rmmod test
创建设备文件:
$ mknod /dev/test c major minor
c 是指字符设备,major是主设备号,就是在/proc/devices里看到的。
用shell命令
$ cat /proc/devices | awk "}"
minor是从设备号,设置成0就可以了
现在可以通过设备文件来访问我们的驱动程序了。
测试文件:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
main()
{
int testdev;
int i;
char buf[10];
testdev = open("/dev/test",O_RDWR); //打开设备文件
if ( testdev == -1 )
{
printf("Cann't open file \n");
exit(0);
}
read(testdev,buf,10); //调用系统调用read,把用户的缓冲区全部写1
for (i = 0; i < 10;i++)
printf("%d\n",buf[i]);
close(testdev); //关闭设备文件
}