LDD 3 scull pipeモジュール
4495 ワード
LDD第六章scull pipe駆動:スリープと起動のプレゼンテーション
scull pipe構造体:
file_operations構造体:
関数の初期化と終了:
マウントスクリプト:
テスト:
# 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のこの部分はデバッグ時に使用します.
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)