character_device_create

This commit is contained in:
Ciro Santilli
2017-08-06 12:21:05 +01:00
parent b2459d07f5
commit dab04d1852
6 changed files with 84 additions and 22 deletions

View File

@@ -31,6 +31,7 @@
1. [dep](dep.c)
1. [dep2](dep2.c)
1. [character_device](character_device.c)
1. [character_device_create](character_device_create.c)
1. [virt_to_phys](virt_to_phys.c)
1. Hardware device drivers
1. [pci_min](pci_min.c)

View File

@@ -19,38 +19,31 @@ and use that for the mknod.
- https://unix.stackexchange.com/questions/37829/understanding-character-device-or-character-special-files/371758#371758
*/
#include <asm/uaccess.h> /* copy_from_user, copy_to_user */
#include <linux/errno.h> /* EFAULT */
#include <linux/fs.h> /* register_chrdev, unregister_chrdev */
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/printk.h> /* printk */
#include <uapi/linux/stat.h> /* S_IRUSR */
#include <linux/seq_file.h> /* seq_read, seq_lseek, single_release */
#define NAME "lkmc_character_device"
static int major;
static ssize_t read(struct file *filp, char __user *buf, size_t len, loff_t *off)
static int show(struct seq_file *m, void *v)
{
size_t ret;
char kbuf[] = {'a', 'b', 'c', 'd'};
seq_printf(m, "abcd");
return 0;
}
ret = 0;
if (*off == 0) {
if (copy_to_user(buf, kbuf, sizeof(kbuf))) {
ret = -EFAULT;
} else {
ret = sizeof(kbuf);
*off = 1;
}
}
return ret;
static int open(struct inode *inode, struct file *file)
{
return single_open(file, show, NULL);
}
static const struct file_operations fops = {
.llseek = seq_lseek,
.open = open,
.owner = THIS_MODULE,
.read = read,
.read = seq_read,
.release = single_release,
};
static int myinit(void)

View File

@@ -0,0 +1,61 @@
/*
Automatically create the device under /dev on insmod, and remove on rmmod.
https://stackoverflow.com/questions/5970595/create-a-device-node-in-code/
https://stackoverflow.com/questions/5970595/how-to-create-a-device-node-from-the-init-module-code-of-a-linux-kernel-module/18594761#18594761
*/
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/fs.h> /* register_chrdev, unregister_chrdev */
#include <linux/module.h>
#include <linux/seq_file.h> /* seq_read, seq_lseek, single_release */
#define NAME "lkmc_character_device_create"
static int major = -1;
static struct cdev mycdev;
static struct class *myclass = NULL;
static int show(struct seq_file *m, void *v)
{
seq_printf(m, "abcd");
return 0;
}
static int open(struct inode *inode, struct file *file)
{
return single_open(file, show, NULL);
}
static const struct file_operations fops = {
.llseek = seq_lseek,
.open = open,
.owner = THIS_MODULE,
.read = seq_read,
.release = single_release,
};
static int myinit(void)
{
/* cat /proc/devices */
alloc_chrdev_region(&major, 0, 1, NAME "_proc");
/* ls /sys/class */
myclass = class_create(THIS_MODULE, NAME "_sys");
/* ls /dev/ */
device_create(myclass, NULL, major, NULL, NAME "_dev");
cdev_init(&mycdev, &fops);
cdev_add(&mycdev, major, 1);
return 0;
}
static void myexit(void)
{
device_destroy(myclass, major);
class_destroy(myclass);
unregister_chrdev_region(major, 1);
}
module_init(myinit)
module_exit(myexit)
MODULE_LICENSE("GPL");

View File

@@ -1,7 +1,7 @@
#!/bin/sh
set -ex
insmod /character_device.ko
/mknoddev.sh lkmc_character_device
cat /dev/lkmc_character_device
# => abcd
[ "$(cat /dev/lkmc_character_device)" = 'abcd' ]
rm /dev/lkmc_character_device
rmmod character_device

View File

@@ -0,0 +1,7 @@
#!/bin/sh
set -ex
insmod /character_device_create.ko
dev='/dev/lkmc_character_device_create_dev'
[ "$(cat "$dev")" = 'abcd' ]
rmmod character_device_create
[ ! -e "$dev" ]