/* example.c */
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int example_init(void) {
printk("<1>EXAMPLE: init\n");
return 0;
}
static void example_exit(void) {
printk("<1>EXAMPLE: exit\n");
}
module_init(example_init);
module_exit(example_exit);
Makefile
obj-m := example.o
ifeq ($(KERNELDIR),)
KERNELDIR=/lib/modules/$(shell uname -r)/build
endif
all:
make -C $(KERNELDIR) M=$(PWD) modules
clean:
make -C $(KERNELDIR) M=$(PWD) clean
$ sudo insmod ./example.ko
$ sudo rmmod example
Use following comamnd to show any message from our kernel.
$ sudo dmesg | tail
Register as Character Device
Add following code into example.c.
#include <linux/fs.h>
static int example_open(struct inode *inode, struct file *filp) {
printk("<1>EXAMPLE: open\n");
return 0;
}
static int example_close(struct inode *inode, struct file *filp) {
printk("<1>EXAMPLE: close\n");
return 0;
}
static ssize_t example_read(struct file *filp, char *buf, size_t size, loff_t *f_pos) {
printk("<1>EXAMPLE: read (size=%zu)\n", size);
return 0;
}
static ssize_t example_write(struct file *filp, const char *buf, size_t size, loff_t *f_pos) {
printk("<1>EXAMPLE: write (size=%zu)\n", size);
return size;
}
static struct file_operations example_fops = {
.open = example_open,
.release = example_close,
.read = example_read,
.write = example_write,
};
Change example_init#define EXAMPLE_MAJOR 60
#define EXAMPLE_NAME "example"
static int example_init(void) {
int result;
printk("<1>EXAMPLE: init\n");
/* Register character device */
result = register_chrdev(EXAMPLE_MAJOR, EXAMPLE_NAME, &example_fops);
if (result < 0) {
printk("<1>EXAMPLE: Failed to register character device\n");
return result;
}
return 0;
}
Change example_exitstatic void example_exit(void) {
printk("<1>EXAMPLE: exit\n");
/* Unregister character device */
unregister_chrdev(EXAMPLE_MAJOR, EXAMPLE_NAME);
}
Compile code (example.c) Remove the example from kernel
$ sudo rmmod example
Insert the kernel
$ sudo insmod ./example.ko
Create a node under /dev
$ sudo mknod /dev/example c 60 0
# /dev/example (the path of file),c represent Character Device,60 (Major ID),0 (Minor ID)。 $ sudo chmod 666 /dev/example (permission - all can read and write)
Write message to /dev/example
$ echo -n 'abcd' > /dev/example
Show message
$ sudo dmesg | tail
Read from user space.
Kernel space and user space have different storage address, so can’t load them directly.
Must use the API of copy_from_user() to read from user space.
Add follow code to modify example.c
#include <asm/uaccess.h>
ssize_t example_write(struct file *filp, const char *buf, size_t size, loff_t *f_pos) {
size_t pos;
uint8_t byte;
printk("<1>EXAMPLE: write (size=%zu)\n", size);
for (pos = 0; pos < size; ++pos) {
if (copy_from_user(&byte, buf + pos, 1) != 0) {
break;
}
printk("<1>EXAMPLE: write (buf[%zu] = %02x)\n", pos, (unsigned)byte);
}
return pos;
}
If data want copy from kernel space to user space must use copy_to_user().
Remove the example from kernel
$ sudo rmmod example
Insert the kernel
$ sudo insmod ./example.ko
Show message
$ sudo dmesg | tail
Reference:
0 意見:
張貼留言