首先看看我自己编的一个驱动模块,下面是源码: asdf.c
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/config.h>
#include<linux/module.h> MODULE_LICENSE("GPL");
#ifdef CONFIG_SMP
#define __SMP__
#endif
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <asm/uaccess.h>
#include "asdf.h"
static int asdf_init()
{
printk("hi,this's a simple device file!/n");
asdf_major=register_chrdev(0,"A Simple Device File",&asdf_ops);
if(asdf_major<0) return asdf_major;
printk("The major is %d/n",asdf_major);
return 0;
}
static void asdf_exit()
{
unregister_chrdev(asdf_major,"A Simple Device File");
printk("A Simple Device has been removed,Bye/n");
}
static int asdf_open(struct inode *inode,struct file *filp)
{
printk("^_^:open %s/n",current->comm);
return 0;
}
static int asdf_release(struct inode *inode,struct file *filp)
{
printk("^_^:close/n");
return 0;
}
static ssize_t asdf_read(struct file *filp,char *buf,size_t count,loff_t *f_pos)
{
loff_t pos;
pos = *f_pos;
if((pos==4096)||(count>4096)) return 0;
pos+=count;
if(pos>4096){
count-=(pos-4096);
pos=4096;
}
if(copy_to_user(buf,asdf_body+*f_pos,count)) return -EFAULT;
*f_pos=pos;
return count;
}
static ssize_t asdf_write(struct file *filp,const char *buf,size_t count,loff_t *f_pos)
{
loff_t pos;
pos = *f_pos;
if((pos==4096)||(count>4096)) return 0;
pos+=count;
if(pos>4096){
count-=(pos-4096);
pos=4096;
}
if(copy_from_user(asdf_body+*f_pos,buf,count)) return -EFAULT;
*f_pos=pos;
return count;
}
static loff_t asdf_lseek(struct file *file,loff_t offset,int orig)
{
loff_t pos;
pos=file->f_pos;
switch(orig){
case 0: pos = offset;
break;
case 1: pos += offset;
break;
case 2: pos = 4096 + offset;
break;
default:
return -EINVAL;
}
if((pos>4096)||(pos<0)){
printk("^_^:lseek error %d/n",pos);
return -EINVAL;
}
return file->f_pos = pos;
}
module_init(asdf_init);
module_exit(asdf_exit);
asdf.h如下:
static int asdf_open(struct inode *inode,struct file *filp);
static int asdf_release(struct inode *inode,struct file *filp);
static ssize_t asdf_read(struct file *filp,char *buf,size_t count,loff_t *f_pos);
static ssize_t asdf_write(struct file *filp,const char *buf,size_t count,loff_t *f_pos);
static loff_t asdf_lseek(struct file *file,loff_t offset,int orig);
struct file_operations asdf_ops={
.open= asdf_open,
.release= asdf_release,
.read= asdf_read,
.write= asdf_write,
.llseek= asdf_lseek,
};
static asdf_major;
static u8 asdf_body[4096]="asdf_body,this message come from the kernel/n";
完成之后,使用2.4编译方法编译成模块,能生成asdf.o文件,但是无法加载到内核,必须错新编写一个Makefile来编译:
obj-m :=asdf.o
KDIR :=/lib/modules/$(shell uname -r)/build
PWD :=$(shell pwd)
default :
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
rm -f *.o *.ko *.mod.c *~
编译通过后查看一下,发现生成asdf.o,asdf.mod.c和asdf.ko,看了新版的LINUX驱动程序发现*.ko是由asdf.o和asdf.mod.c 生成的 ,然后就可以按这老步骤insmod asdf.ko -> mknod /dev/asdf c 254 0
下面是一个简单的测试程序,可供参考:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void main()
{
int asdf;
char buf[1024];
asdf=open("/dev/asdf",O_RDWR);
if(asdf==-1)
{
printf("cant open file/n");
exit(0);
}
read(asdf,buf,1024);
printf("the message from asdf dev is: %s/n",buf);
close(asdf);
}
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/config.h>
#include<linux/module.h> MODULE_LICENSE("GPL");
#ifdef CONFIG_SMP
#define __SMP__
#endif
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <asm/uaccess.h>
#include "asdf.h"
static int asdf_init()
{
printk("hi,this's a simple device file!/n");
asdf_major=register_chrdev(0,"A Simple Device File",&asdf_ops);
if(asdf_major<0) return asdf_major;
printk("The major is %d/n",asdf_major);
return 0;
}
static void asdf_exit()
{
unregister_chrdev(asdf_major,"A Simple Device File");
printk("A Simple Device has been removed,Bye/n");
}
static int asdf_open(struct inode *inode,struct file *filp)
{
printk("^_^:open %s/n",current->comm);
return 0;
}
static int asdf_release(struct inode *inode,struct file *filp)
{
printk("^_^:close/n");
return 0;
}
static ssize_t asdf_read(struct file *filp,char *buf,size_t count,loff_t *f_pos)
{
loff_t pos;
pos = *f_pos;
if((pos==4096)||(count>4096)) return 0;
pos+=count;
if(pos>4096){
count-=(pos-4096);
pos=4096;
}
if(copy_to_user(buf,asdf_body+*f_pos,count)) return -EFAULT;
*f_pos=pos;
return count;
}
static ssize_t asdf_write(struct file *filp,const char *buf,size_t count,loff_t *f_pos)
{
loff_t pos;
pos = *f_pos;
if((pos==4096)||(count>4096)) return 0;
pos+=count;
if(pos>4096){
count-=(pos-4096);
pos=4096;
}
if(copy_from_user(asdf_body+*f_pos,buf,count)) return -EFAULT;
*f_pos=pos;
return count;
}
static loff_t asdf_lseek(struct file *file,loff_t offset,int orig)
{
loff_t pos;
pos=file->f_pos;
switch(orig){
case 0: pos = offset;
break;
case 1: pos += offset;
break;
case 2: pos = 4096 + offset;
break;
default:
return -EINVAL;
}
if((pos>4096)||(pos<0)){
printk("^_^:lseek error %d/n",pos);
return -EINVAL;
}
return file->f_pos = pos;
}
module_init(asdf_init);
module_exit(asdf_exit);
asdf.h如下:
static int asdf_open(struct inode *inode,struct file *filp);
static int asdf_release(struct inode *inode,struct file *filp);
static ssize_t asdf_read(struct file *filp,char *buf,size_t count,loff_t *f_pos);
static ssize_t asdf_write(struct file *filp,const char *buf,size_t count,loff_t *f_pos);
static loff_t asdf_lseek(struct file *file,loff_t offset,int orig);
struct file_operations asdf_ops={
.open= asdf_open,
.release= asdf_release,
.read= asdf_read,
.write= asdf_write,
.llseek= asdf_lseek,
};
static asdf_major;
static u8 asdf_body[4096]="asdf_body,this message come from the kernel/n";
完成之后,使用2.4编译方法编译成模块,能生成asdf.o文件,但是无法加载到内核,必须错新编写一个Makefile来编译:
obj-m :=asdf.o
KDIR :=/lib/modules/$(shell uname -r)/build
PWD :=$(shell pwd)
default :
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
rm -f *.o *.ko *.mod.c *~
编译通过后查看一下,发现生成asdf.o,asdf.mod.c和asdf.ko,看了新版的LINUX驱动程序发现*.ko是由asdf.o和asdf.mod.c 生成的 ,然后就可以按这老步骤insmod asdf.ko -> mknod /dev/asdf c 254 0
下面是一个简单的测试程序,可供参考:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void main()
{
int asdf;
char buf[1024];
asdf=open("/dev/asdf",O_RDWR);
if(asdf==-1)
{
printf("cant open file/n");
exit(0);
}
read(asdf,buf,1024);
printf("the message from asdf dev is: %s/n",buf);
close(asdf);
}