LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1008|回复: 3

驱动模块出现段错误!恳请高手帮忙!小弟快不行了!

[复制链接]
发表于 2007-7-3 20:57:56 | 显示全部楼层 |阅读模式
以下是驱动模块代码:
#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/slab.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <linux/proc_fs.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/fcntl.h>
#include <asm/system.h>
//#include <linux/kdev_t.h>
//#include <sys/types.h>

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<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(!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 <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 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;
}
 楼主| 发表于 2007-7-3 21:17:53 | 显示全部楼层
以下是错误输出:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

发表于 2007-7-17 17:02:54 | 显示全部楼层
e.txt的内容呢?
另外,“0,0^_^opening^_^"这个提示程序中找不到?
回复 支持 反对

使用道具 举报

发表于 2007-7-19 13:36:00 | 显示全部楼层
e.txt 的内容就是图片中的信息..
用Valgrind试试,可以找到SGV的出错位置.
回复 支持 反对

使用道具 举报

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

本版积分规则

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