LDD 3 scull pipeモジュール

4495 ワード

LDD第六章scull pipe駆動:スリープと起動のプレゼンテーション
scull pipe構造体:
struct scullp_dev {
        wait_queue_head_t inq, outq;       /* read and write queues */
        char *buffer, *end;                /* begin of buf, end of buf */
        int buffersize;                    /* used in pointer arithmetic */
        char *rp, *wp;                     /* where to read, where to write */
        int nreaders, nwriters;            /* number of openings for r/w */
        struct fasync_struct *async_queue; /* asynchronous readers */
        struct semaphore sem;              /* mutual exclusion semaphore */
        struct cdev cdev;                  /* Char device structure */
};
int scullp_major =   0;         //  
int scullp_minor =   0;         //  
int scullp_nr_devs = 1;         //   
int scull_p_buffer =  4000;     //  

file_operations構造体:
/*
 * The file operations for the pipe device
 * (some are overlayed with bare scull)
 */
struct file_operations scull_pipe_fops = {
	.owner =	THIS_MODULE,
	.llseek =	no_llseek,
	.read =		scull_p_read,
	.write =	scull_p_write,
	.poll =		scull_p_poll,
	.open =		scull_p_open,
	.release =	scull_p_release,
	.fasync =	scull_p_fasync,
};

関数の初期化と終了:
/*
 * Set up the char_dev structure for this device.
 */
static void scullp_setup_cdev(struct scullp_dev *dev, int index)
{
	int err, devno = MKDEV(scullp_major, scullp_minor + index);
    
	cdev_init(&dev->cdev, &scull_pipe_fops);
	dev->cdev.owner = THIS_MODULE;
	dev->cdev.ops = &scull_pipe_fops;
	err = cdev_add (&dev->cdev, devno, 1);
	/* Fail gracefully if need be */
	if (err)
		printk(KERN_NOTICE "Error %d adding scull%d", err, index);
}


void scullp_cleanup_module(void)
{
	int i;
	dev_t devno = MKDEV(scullp_major, scullp_minor);

	if (!scullp_dev)
		return; /* nothing else to release */

	for (i = 0; i < scullp_nr_devs; i++) {
		cdev_del(&scullp_dev[i].cdev);
		kfree(scullp_dev[i].buffer);
	}
	kfree(scullp_dev);
	unregister_chrdev_region(devno, scullp_nr_devs);
	scullp_dev = NULL; /* pedantic */

}


int scullp_init(void)
{
	int result, i;
	dev_t dev = 0;

/*
 * Get a range of minor numbers to work with, asking for a dynamic
 * major unless directed otherwise at load time.
 */
	if (scullp_major) {
		dev = MKDEV(scullp_major, scullp_minor);
		result = register_chrdev_region(dev, scullp_nr_devs, "scullp");
	} else {
		result = alloc_chrdev_region(&dev, scullp_minor, scullp_nr_devs,
				"scullp");
		scullp_major = MAJOR(dev);
	}
	if (result < 0) {
		printk(KERN_WARNING "scull: can't get major %d
", scullp_major); return result; } /* * allocate the devices -- we can't have them static, as the number * can be specified at load time */ scullp_dev = kmalloc(scullp_nr_devs * sizeof(struct scullp_dev), GFP_KERNEL); if (!scullp_dev) { result = -ENOMEM; goto fail; /* Make this more graceful */ } memset(scullp_dev, 0, scullp_nr_devs * sizeof(struct scullp_dev)); /* Initialize each device. */ for (i = 0; i < scullp_nr_devs; i++) { init_waitqueue_head(&(scullp_dev[i].inq)); init_waitqueue_head(&(scullp_dev[i].outq)); init_MUTEX(&scullp_dev[i].sem); scullp_setup_cdev(scullp_dev + i, i); } return 0; /* succeed */ fail: scullp_cleanup_module(); return result; } module_init(scullp_init); module_exit(scullp_cleanup_module);

マウントスクリプト:
#!/bin/sh

module="scull"
device="scull"
mode="664"

/sbin/insmod ./$module.ko $* || exit 1
major=$(awk "\$2==\"$module\" {print \$1}" /proc/devices)


# scull pipe
rm -f /dev/${device}p 
mknod /dev/${device}p c $major 0

テスト:
# cat/dev/scullp &
scull: "cat"reading: going to sleep
#echo“hello”>/dev/scullp scull:Going to accept 6 bytes to c 39 c 2000 from 4000000 scull:“sh”did write 6 bytes scull:“cat”did read 6 bytes hscull:“cat”reading:going to sleep elloすべてのコードはここにあります
また、Makefileのこの部分はデバッグ時に使用します.
# enable / disable debugging and 
# don't forget to set current log level to 8: 
# echo 8 >/proc/sys/kernel/printk
# run this command on your mini2440 develop board

DEBUG = y
ifeq ($(DEBUG),y)
	DEBFLAGS = -DSCULL_DEBUG
else
	DEBFLAGS = 
endif
EXTRA_CFLAGS += $(DEBFLAGS)