QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 1054|回复: 1

LINUX设备驱动程序一书中scull例子问题.

[复制链接]
发表于 2005-6-15 22:25:52 | 显示全部楼层 |阅读模式
我照书上输入如下代码:

#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;
}

哪位大侠帮我看看,万分感谢!
我头都搞晕了,快不行了.
发表于 2005-6-18 22:38:34 | 显示全部楼层
楼上的镇有精力啊,这些源码电力出版社又下载阿,你真的一行一行敲进去了?佩服死了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-5 19:35 , Processed in 0.103031 second(s), 15 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表