经过近一个月的努力,终于熟悉了Linux下的驱动和应用程序开发流程。
Linux内核支持可插入式模块,驱动程序可以编译在内核中,也可以编译为内核的模块文件。这点和应用程序差不多。常见的驱动程序是作为模块动态加载的,比如声卡,网卡等。而Linux最基本的驱动,如CPU,PCI总线,TCP/IP,APM,VFS等则直接编译到内核文件中。
下面以一个简单的字符型设备驱动为例:
./a.c
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
#define DEVICE_NAME "qq_char"
unsigned int fs_major = 0;
static ssize_t test_read(struct file *file, char *buf, size_t count, loff_t *f_pos);
static int test_open(struct inode *node, struct file *file);
static int test_release(struct inode *inode, struct file *file);
static struct file_operations char_fops =
{
read: test_read,
open: test_open,
release: test_release
};
static ssize_t test_read(struct file *file, char *buf, size_t count, loff_t *f_pos)
{
int len;
for(len = count; len > 0; len--){
put_user(1, buf); // 将数据放入用户空间的buf中
buf++;
}
return count;
}
// 打开设备
static int test_open(struct inode *node, struct file *file)
{
return 0;
}
// 释放设备
static int test_release(struct inode *inode, struct file *file)
{
return 0;
}
// 注册设备
int init_test(void)
{
int res;
res = register_chrdev(0, DEVICE_NAME, &char_fops);
if(res < 0){
printk("can't get major name!\n");
return res;
}
if(fs_major == 0)
fs_major = res;
printk("now, i am in kernel mode!\n");
return 0;
}
// 卸载设备
void cleanup_test(void)
{
printk("now, i am out of kernel\n");
unregister_chrdev(fs_major, DEVICE_NAME);
}
module_init(init_test);
module_exit(cleanup_test);
编译后,如果是2.6版本,则会生成a.ko
执行insmod a.ko后,内核调用module_init(),从而调用register_chrdev()函数注册该设备。
如果注册成功,则会在/proc/devices下面看到DEVICE_NAME,也就是qq_char,以及主设备号和次设备号,这就是注册了的设备。
如果想卸载设备,则rmmod a,内核调用module_exit(),从而调用unregister_chrdev(),卸载掉该设备。
注册完设备之后,因为/proc是个伪文件系统,/proc/devices下面的qq_char并不是真正的设备文件,所以还要将该设备映射为设备文件。
mknod /dev/qq_char c 253 0
生成设备文件后,可以在/dev下面看到qq_char。好了,到现在为止,我们的设备驱动已经做好了。
下面我们用一个简单的应用程序来测试这个驱动。
./aa.c
#include <stdio.h>
#include <sys/types.h> // pid_t
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
int main(void)
{
int testdev;
int i;
char buf[10];
testdev = open("/dev/qq_char", O_RDWR); // 打开设备qq_char
if(testdev == -1){
printf("cann't open file \n");
exit(0);
}
printf("now read \n");
read(testdev, buf, 10); // 从qq_char读数据到buf中
printf("read end \n");
for(i = 0; i < 10; i++){
printf("%d\n", buf);
}
close(testdev);
return 0;
}
编译,运行该程序,产生如下结果
now read
read end
1
1
1
1
1
1
1
1
1
1
成功!
文章评论(0条评论)
登录后参与讨论