-

   rss_rss_hh_new

 - e-mail

 

 -

 LiveInternet.ru:
: 17.03.2011
:
:
: 51

:


[ ] Linux device driver

, 14 2017 . 15:50 +
Alexeynew 15:50

Linux device driver

, .

Linux, .

, , , . ( ).

, !

P.S

, :

1 , .
2 open, read, write trim.
3 Makefile .

, , , .

, .


(Char driver) , , / .

scull_dev, cdev .

struct scull_dev {
	struct scull_qset *data;  /*      */
	int quantum;		  /*     */
	int qset;		  /*    */
	unsigned long size;	  /*    */
	struct semaphore sem;     /*   */
	struct cdev cdev;	  /* ,    */
};

struct scull_dev *scull_device;

, scull_qset.

struct scull_qset {
	void **data;
	struct scull_qset *next;
};

.

image

, , :

MAJOR ( ).
MINOR ( ).

, , , .

, . file_operations.

struct file_operations scull_fops = {
	.owner = THIS_MODULE,
	.read = scull_read,
	.write = scull_write,
	.open = scull_open,
	.release = scull_release,
};

module_init/module_exit, / . / .

module_init(scull_init_module);
module_exit(scull_cleanup_module);

.

int scull_major = 0;		/* MAJOR */
int scull_minor = 0;		/* MINOR */
int scull_nr_devs = 1;		/*    */
int scull_quantum = 4000;	/*     */
int scull_qset = 1000;		/*    */

.
, , : lxr

#include module.h> /*          */
#include init.h>  /*       */
#include fs.h>    /*       */
#include cdev.h>  /*       */
#include slab.h>  /*       */
#include uaccess.h> /*      */


.

static int scull_init_module(void)
{
	int rv, i;
	dev_t dev;

	rv = alloc_chrdev_region(&dev, scull_minor, scull_nr_devs, "scull");	
	scull_major = MAJOR(dev);

	if (rv) {
		printk(KERN_WARNING "scull: can't get major %d\n", scull_major);
		return rv;
	}

	scull_device = kmalloc(scull_nr_devs * sizeof(struct scull_dev), GFP_KERNEL);
	
	if (!scull_device) {
		rv = -ENOMEM;
		goto fail;
	}

	memset(scull_device, 0, scull_nr_devs * sizeof(struct scull_dev));

	for (i = 0; i < scull_nr_devs; i++) {
		scull_device[i].quantum = scull_quantum;
		scull_device[i].qset = scull_qset;
		sema_init(&scull_device[i].sem, 1);
		scull_setup_cdev(&scull_device[i], i);
	}

	dev = MKDEV(scull_major, scull_minor + scull_nr_devs);	

	return 0;

fail:
	scull_cleanup_module();
	return rv;
}

, alloc_chrdev_region . MAJOR(dev) .
, , . , , (NULL?).

rv = alloc_chrdev_region(&dev, scull_minor, scull_nr_devs, "scull");	
	scull_major = MAJOR(dev);

if (rv) {
	printk(KERN_WARNING "scull: can't get major %d\n", scull_major);
	return rv;
}

.

, kmalloc NULL.

scull_device = kmalloc(scull_nr_devs * sizeof(struct scull_dev), GFP_KERNEL);
	
if (!scull_device) {
	rv = -ENOMEM;
	goto fail;
}

memset(scull_device, 0, scull_nr_devs * sizeof(struct scull_dev));

. scull_setup_cdev, . MKDEV .

for (i = 0; i < scull_nr_devs; i++) {
		scull_device[i].quantum = scull_quantum;
		scull_device[i].qset = scull_qset;
		sema_init(&scull_device[i].sem, 1);
		scull_setup_cdev(&scull_device[i], i);
	}

	dev = MKDEV(scull_major, scull_minor + scull_nr_devs);

.

return 0;

fail:
	scull_cleanup_module();
	return rv;
}

scull_dev cdev, . scull_setup_cdev .

static void scull_setup_cdev(struct scull_dev *dev, int index)
{
	int err, devno = MKDEV(scull_major, scull_minor + index);

	cdev_init(&dev->cdev, &scull_fops); 

	dev->cdev.owner = THIS_MODULE;
	dev->cdev.ops = &scull_fops;

	err = cdev_add(&dev->cdev, devno, 1);

	if (err)
		printk(KERN_NOTICE "Error %d adding scull  %d", err, index);
}


scull_cleanup_module .
, , .

void scull_cleanup_module(void)
{
	int i;
	dev_t devno = MKDEV(scull_major, scull_minor);

	if (scull_device) {
		for (i = 0; i < scull_nr_devs; i++) {
			scull_trim(scull_device + i);
			cdev_del(&scull_device[i].cdev);	
		}
		
		kfree(scull_device);
	}

	unregister_chrdev_region(devno, scull_nr_devs); 
}

#include module.h> 	
#include init.h> 	
#include fs.h> 		
#include cdev.h> 	
#include slab.h> 	
#include uaccess.h>

int scull_major = 0;		
int scull_minor = 0;		
int scull_nr_devs = 1;		
int scull_quantum = 4000;	
int scull_qset = 1000;	

struct scull_qset {
	void **data;			
	struct scull_qset *next; 	
};

struct scull_dev {
	struct scull_qset *data;  
	int quantum;		 
	int qset;		  
	unsigned long size;	  
	unsigned int access_key;  
	struct semaphore sem;    
	struct cdev cdev;	 
};

struct scull_dev *scull_device;

int scull_trim(struct scull_dev *dev)
{
	struct scull_qset *next, *dptr;
	int qset = dev->qset; 
	int i;

	for (dptr = dev->data; dptr; dptr = next) { 
		if (dptr->data) {
			for (i = 0; i < qset; i++)
				kfree(dptr->data[i]);

			kfree(dptr->data);
			dptr->data = NULL;
		}

		next = dptr->next;
		kfree(dptr);
	}

	dev->size = 0;
	dev->quantum = scull_quantum;
	dev->qset = scull_qset;
	dev->data = NULL;

	return 0;
}

struct file_operations scull_fops = {		
	.owner = THIS_MODULE,			
	//.read = scull_read,
	//.write = scull_write,
	//.open = scull_open,
	//.release = scull_release,
};

static void scull_setup_cdev(struct scull_dev *dev, int index)
{
	int err, devno = MKDEV(scull_major, scull_minor + index);	

	cdev_init(&dev->cdev, &scull_fops);

	dev->cdev.owner = THIS_MODULE;
	dev->cdev.ops = &scull_fops;

	err = cdev_add(&dev->cdev, devno, 1);

	if (err)
		printk(KERN_NOTICE "Error %d adding scull  %d", err, index);
}

void scull_cleanup_module(void)
{
	int i;
	dev_t devno = MKDEV(scull_major, scull_minor);

	if (scull_device) {
		for (i = 0; i < scull_nr_devs; i++) {
			scull_trim(scull_device + i);		
			cdev_del(&scull_device[i].cdev);	
		}
		
		kfree(scull_device);
	}

	unregister_chrdev_region(devno, scull_nr_devs); 
}

static int scull_init_module(void)
{
	int rv, i;
	dev_t dev;

		
	rv = alloc_chrdev_region(&dev, scull_minor, scull_nr_devs, "scull");	
	scull_major = MAJOR(dev);

	if (rv) {
		printk(KERN_WARNING "scull: can't get major %d\n", scull_major);
		return rv;
	}

	scull_device = kmalloc(scull_nr_devs * sizeof(struct scull_dev), GFP_KERNEL);	
	
	if (!scull_device) {
		rv = -ENOMEM;
		goto fail;
	}

	memset(scull_device, 0, scull_nr_devs * sizeof(struct scull_dev));		

	for (i = 0; i < scull_nr_devs; i++) {						
		scull_device[i].quantum = scull_quantum;
		scull_device[i].qset = scull_qset;
		sema_init(&scull_device[i].sem, 1);
		scull_setup_cdev(&scull_device[i], i);					
	}

	dev = MKDEV(scull_major, scull_minor + scull_nr_devs);	
	
	printk(KERN_INFO "scull: major = %d minor = %d\n", scull_major, scull_minor);

	return 0;

fail:
	scull_cleanup_module();
	return rv;
}

MODULE_AUTHOR("Your name");
MODULE_LICENSE("GPL");

module_init(scull_init_module);		
module_exit(scull_cleanup_module);	


feedback'a.

, , .
.

!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/337946/

:  

: [1] []
 

:
: 

: ( )

:

  URL