|
我照书上输入如下代码:
#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 <linux/config.h>
#define MODULE
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <asm/uaccess.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/errno.h>
MODULE_LICENSE("GPL");
#define HELLO_PORT_FLOOR 0x280
#define HELLO_PORT_CELL 0x300
#define HELLO_PORT_RANGE 0x010
static int hello_port_base = HELLO_PORT_FLOOR;
static int hello_port_len = HELLO_PORT_RANGE;
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_port_base,"i");
MODULE_PARM_DESC (hello_port_base,"Base I/O port for hello!");
MODULE_PARM(hello_port_len,"i");
MODULE_PARM(hello_major,"i");
MODULE_PARM(hello_quantum,"i");
MODULE_PARM(hello_qset,"i");
MODULE_PARM(hello_nr_devs,"i");
struct hello_Dev * hello_devices;
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;
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 < qset; 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(!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 = kmalloc(sizeof(hello_Dev), GFP_KERNEL);
// dev->next = kmalloc(sizeof(hello_Dev),GFP_KERNEL);
memset(dev->next,0,sizeof(hello_Dev));
}
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 = 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 = 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 = -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 = 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] = 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 *file)
{
return 0;
}
struct file_operations hello_fops= {
open: hello_open,
read: hello_read,
write: hello_write,
release: hello_release};
void hello_prelease(unsigned int port,unsigned int range)
{
release_region(port,range);
}
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;
}
if (hello_major == 0) hello_major = result;
return 0;
}
void __exit end_cleanup(void)
{
hello_prelease(hello_port_base,hello_port_len);
unregister_chrdev(hello_major,"hello");
printk("<1>Goodbye cruel world!\n");
}
module_init(start_init);
module_exit(end_cleanup);
编译能通过,但在每个调用:kmalloc 的句语上都有警告:assignment makes pointer from integer without a cast;
我用生成的hello.o加载没有错误,但是当我写一个测试程序时,出现段错误!
测试程序如下:
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
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 hello 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);
count = read(hello_fd,readchar,100);
printf("Driver info is : %s\n",readchar);
fflush(stdout);
close(hello_fd);
return 0;
}
哪位大侠帮我看看,万分感谢!
我头都搞晕了,快不行了. |
|