以下是驱动模块代码:
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef HELLO_QUANTUM
#define HELLO_QUANTUM 4000
#endif
#ifndef HELLO_QSET
#define HELLO_QSET 1000
#endif
#ifndef HELLO_NR_DEVS
#define HELLO_NR_DEVS 1
#endif
#include
#define MODULE
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
//#include
MODULE_LICENSE("GPL");
static int hello_major=0;
int hello_quantum=HELLO_QUANTUM;
int hello_qset=HELLO_QSET;
int hello_nr_devs=HELLO_NR_DEVS;
MODULE_PARM(hello_major,"i");
MODULE_PARM(hello_quantum,"i");
MODULE_PARM(hello_qset,"i");
MODULE_PARM(hello_nr_devs,"i");
struct file_operations hello_fops;
struct file_operations *hello_fop_array[]={&hello_fops};
#define HELLO_MAX_TYPE 1
#define TYPE(dev) (MINOR(dev)>>4)
#define NUM(dev) (MINOR(dev)&0xf)
typedef struct hello_Dev{
void **data;
struct hello_Dev *next;
int quantum;
int qset;
unsigned long size;
unsigned int access_key;
struct semaphore sem;
}hello_Dev;
struct hello_Dev *hello_devices;
int hello_trim(hello_Dev *dev)
{
hello_Dev *next,*dptr;
int qset=dev->qset;
int i;
for(dptr=dev;dptr;dptr=next)
{
if(dptr->data)
{
for(i=0;i
{
if(dptr->data)
kfree(dptr->data);
}
kfree(dptr->data);
dptr->data=NULL;
}
next=dptr->next;
if (dptr != dev) kfree(dptr);
}
dev->size=0;
dev->quantum=hello_quantum;
dev->qset=hello_qset;
dev->next=NULL;
return 0;
}
int hello_open(struct inode *inode,struct file *filp)
{
hello_Dev *dev;
int num=NUM(inode->i_rdev) ;
int type=TYPE(inode->i_rdev);
if(!num &&! type)
printk("%d,%d",num,type);
if(!filp->private_data && type)
{
if(type>HELLO_MAX_TYPE)
return -ENODEV;
filp->f_op=hello_fop_array[type];
return filp->f_op->open(inode,filp);
}
dev=(hello_Dev *)filp->private_data;
if(!dev){
if(num>=hello_nr_devs)
return -ENODEV;
dev=&hello_devices[num];
filp->private_data=dev;
}
MOD_INC_USE_COUNT;
if((filp->f_flags & O_ACCMODE) == O_WRONLY)
{
if(down_interruptible(&dev->sem))
{
MOD_DEC_USE_COUNT;
return -ERESTARTSYS;
}
hello_trim(dev);
up(&dev->sem);
}
return 0;
}
hello_Dev *hello_follow(hello_Dev *dev,int n)
{
while(n--)
{
if(!dev->next)
{
dev->next=(hello_Dev *)kmalloc(sizeof(hello_Dev),GFP_KERNEL);
memset(dev->next,0,sizeof(hello_Dev));
//dev->next->data=NULL;
}
dev=dev->next;
continue;
}
return dev;
}
ssize_t hello_read(struct file *filp,char *buf,size_t count,loff_t *f_pos)
{
hello_Dev *dev=(hello_Dev *)filp->private_data;
hello_Dev *dptr;
int quantum=dev->quantum;
int qset=dev->qset;
int itemsize=quantum*qset;
int item,s_pos,q_pos,rest;
ssize_t ret=0;
if(down_interruptible(&dev->sem))
{
return -ERESTARTSYS;
}
if(*f_pos>=dev->size)
{
goto out;
}
if(*f_pos+count>dev->size)
{
count=dev->size-*f_pos;
}
item=(long)*f_pos/itemsize;
rest=(long)*f_pos%itemsize;
s_pos=rest/quantum;
q_pos=rest%quantum;
dptr=hello_follow(dev,item);
if(!dptr->data)
{
goto out;
}
if(!dptr->data[s_pos])
{
goto out;
}
if(count>quantum-q_pos)
{
count=quantum-q_pos;
}
if(copy_to_user(buf,dptr->data[s_pos]+q_pos,count))
{
ret=-EFAULT;
goto out;
}
*f_pos+=count;
ret=count;
out:
up(&dev->sem);
return ret;
}
ssize_t hello_write(struct file *filp,const char *buf,size_t count,loff_t *f_pos)
{
hello_Dev *dev=(hello_Dev *)filp->private_data;
hello_Dev *dptr;
int quantum=dev->quantum;
int qset=dev->qset;
long itemsize=quantum*qset;
int item,s_pos,q_pos,rest;
ssize_t ret=-ENOMEM;
if(down_interruptible(&dev->sem))
{
return -ERESTARTSYS;
}
item=(long)*f_pos/itemsize;
rest=(long)*f_pos%itemsize;
s_pos=rest/quantum;
q_pos=rest%quantum;
dptr=hello_follow(dev,item);
if(!dptr->data)
{
dptr->data=(void *)kmalloc(qset*sizeof(char *),GFP_KERNEL);
if(!dptr->data)
{
goto out;
}
memset(dptr->data,0,qset*sizeof(char *));
}
if(!dptr->data[s_pos])
{
dptr->data[s_pos]=(void *)kmalloc(quantum,GFP_KERNEL);
if(!dptr->data[s_pos])
{
goto out;
}
}
if(count>quantum-q_pos)
{
count=quantum-q_pos;
}
if(copy_from_user(dptr->data[s_pos]+q_pos,buf,count))
{
ret=-EFAULT;
goto out;
}
*f_pos+=count;
ret=count;
if(dev->size<*f_pos)
dev->size=*f_pos;
out:
up(&dev->sem);
return ret;
}
int hello_release(struct inode *inode,struct file *filp)
{
MOD_DEC_USE_COUNT;
return 0;
}
struct file_operations hello_fops={
open: hello_open,
read: hello_read,
write: hello_write,
release: hello_release,
};
int __init start_init(void)
{
printk("<1>Hello,world!\n");
printk("<1>The process is %s (pid %i)\n",current->comm,current->pid);
int result=register_chrdev(hello_major,"hello",&hello_fops);
if(result<0)
{
printk(KERN_WARNING "hello:can't get major %d\n",hello_major);
return result;
}
if(hello_major==0)
{
hello_major=result;
}
return 0;
}
void __exit end_cleanup(void)
{
int hello_release(struct inode * inode, struct file * filp);
unregister_chrdev(hello_major,"hello");
printk("<1>Goofbye cruel world!\n");
}
module_init(start_init);
module_exit(end_cleanup);
以下是测试程序代码:
#include
#include
#include
int main(int argc,char *argv[])
{
char *device="/dev/hello";
int hello_fd;
char cBuffer[100];
char readchar[100];
int i,count;
char *constchar;
constchar="This is a hope device driver\n";
sprintf(cBuffer,constchar);
printf("driver info is: %s\n",cBuffer);
fflush(stdout);
hello_fd=open(device,O_RDWR);
if(hello_fd==-1)
{
printf("Unable to open hello device!\n");
exit(0);
}
count=write(hello_fd,cBuffer,100);
close(hello_fd);
hello_fd=open(device,O_RDWR);
if(hello_fd==-1)
{
printf("Unable to open hello device!\n");
exit(0);
}
count=read(hello_fd,readchar,100);
printf("Driver info is : %s\n",readchar);
fflush(stdout);
close(hello_fd);
return 0;
}