scull devices

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,
   I am studying the book LDD3 by rubini.And I am trying to implement
the scull char device driver.And I followed the same procedure as in the
book.
And I implemented only init,exit functions as begining.And I inserted
the module.It is inserting fine.And printing the debug messages
correctly as i given.
But when i try to remove that module,it is comming as segmentation fault
and in the kernel log it is printing as 
Unable to handle kernel NULL pointer dereference at virtual address
00000007

I cannot understand where the wrong is.I am listing the code below.Will
you please help me.



#ifndef __KERNEL__
	#define __KERNEL__
#endif
#ifndef MODULE
	#define MODULE
#endif

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>	// printk()
#include <linux/fs.h>		// every thing
#include <linux/cdev.h>		// representing char drivers with in the kernel
#include <linux/slab.h>		// for kmalloc,kfree
#include <linux/errno.h>	/* error codes */
#include <linux/types.h>	/* size_t */
/*
 * Representation of scull quantum sets.
 */
typedef struct scull_qset {
	void **data;
	struct scull_qset *next;
}scull_qset_t;
//
typedef struct scull_dev{
	scull_qset_t *data;	// pointer to first quantem set
	int quantum;		// the current quantum size
	int qset;		//The current array size
	unsigned long size;	// Amount Of Data Stored here
	unsigned int access_key;	// used by sculluid and scullpriv
	struct semaphore sem;	//mutual exclusion semaphore
	struct cdev cdev;	//Char device structure 
}scull_dev_t; 


//file operations
struct file_operations scull_fops = {
	.owner = THIS_MODULE
};


/*
 * The bare device is a variable-length region of memory.
 * Use a linked list of indirect blocks.
 *
 * "scull_dev->data" points to an array of pointers, each
 * pointer refers to a memory area of SCULL_QUANTUM bytes.
 *
 * The array (quantum-set) is SCULL_QUANTUMSET long.
 */
#ifndef SCULL_QUANTUM
	#define SCULL_QUANTUM 4000
#endif

#ifndef SCULL_QUANTUMSET
	#define SCULL_QUANTUMSET    1000
#endif
#define SCULL_MAJOR 0	//default Major number
#define NO_OF_DEVICES 4	//No Of Devices


static int __init scull_init(void);
static void __exit scull_exit(void);

#define DEVICE_NAME "SCULL"

MODULE_AUTHOR("RAJA");
MODULE_DESCRIPTION("SCULL DEVICE");
MODULE_LICENSE("GPL");

extern int scull_major;
extern int scull_minor;
extern int no_of_devices;
extern int scull_quantum;
extern int scull_qset;


//different configurable parameters
int scull_major = SCULL_MAJOR;
int scull_minor = 0;
int no_of_devices = NO_OF_DEVICES;
int scull_quantum = SCULL_QUANTUM;
int scull_qset = SCULL_QUANTUMSET;

struct scull_dev *scull_devices;	/* allocated in scull_init_module */

// Initialization of sculldev_t structure
static void setup_sculldev(scull_dev_t *device,int index)
{
	printk("Entered Into setup_sculldev Function \n");
	int err;
	int devNo = MKDEV(scull_major,scull_minor + index);
	cdev_init(&(device->cdev),&scull_fops);
	device->cdev.owner = THIS_MODULE;
	device->cdev.ops = &scull_fops;
	err = cdev_add(&(device->cdev),devNo,1);
	if(err)
		printk(KERN_NOTICE "Error : %d Adding %d device",err,index);
	printk("Returned From setup_sculldev Function \n");
}
/*
// freeing the whole data area
int scull_trim(sculldev_t *device)
{


}
*/
static int __init scull_init()
{
	printk("Entered Into Init Function \n");
	int result;
	dev_t dev;
	// registering the chrdev region
	if(scull_major)
	{
		dev = MKDEV(scull_major,scull_minor);
		register_chrdev_region(dev,no_of_devices,DEVICE_NAME);
	}else
	  {
		result = alloc_chrdev_region(&dev,scull_minor,no_of_devices,DEVICE_NAME);
		scull_major = MAJOR(dev);
	  }
	if(result < 0)
	{
		printk("Failed To Allocate chrdev Region\n");
		return result;
	}else
		printk("chrdev Region Allocated \n");
	// Allocating The Devices
	scull_devices = kmalloc(GFP_KERNEL,sizeof(scull_dev_t) * no_of_devices);
	if(!scull_devices)	
	{
		result = -ENOMEM;
		goto fail;
	}
	memset(scull_devices,0,sizeof(scull_dev_t) * no_of_devices);
	int i;
	for(i=0;i<no_of_devices;i++)
	{
		scull_devices[i].quantum = SCULL_QUANTUM;
		scull_devices[i].qset = SCULL_QUANTUMSET;
		init_MUTEX(&(scull_devices[i].sem));		
		setup_sculldev(&(scull_devices[i]),i);
	}
	printk("Returned From Init Function \n");
	return 0;
  fail :
	scull_exit();
	printk("Returned From Init Function \n");
	return result;
}

static void __exit scull_exit()
{
	printk("Entered Into Exit Function \n");
	int i;
	dev_t dev = MKDEV(scull_major,scull_minor);
	if(scull_devices)
	{
		for(i=0;i<no_of_devices;i++)
		{
			cdev_del(&(scull_devices[i].cdev));
		}
		kfree(scull_devices);
	}
	unregister_chrdev_region(dev, no_of_devices);
	printk("Returned From Exit Function \n");
}

module_init(scull_init);
module_exit(scull_exit);



thanks in advance.
raja


--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive:       http://mail.nl.linux.org/kernelnewbies/
FAQ:           http://kernelnewbies.org/faq/


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux