Create Kernel Driver: Difference between revisions
m Iwiseman moved page Muitipass Setup to Create Kernel Driver |
|||
(4 intermediate revisions by the same user not shown) | |||
Line 39: | Line 39: | ||
*Block Device e.g. fs, drive | *Block Device e.g. fs, drive | ||
*Network Device e.g. nic | *Network Device e.g. nic | ||
=How it works= | |||
User space, talks to kernel space, using system calls. The device drivers implement, two types of systems calls, one type file operations, the other hardware management or ioctl. | |||
=Basic Module= | |||
Here is the basic set up | |||
<syntaxhighlight lang="c"> | |||
// Write kernel module for pyjama | |||
#include <linux/init.h> | |||
#include <linux/module.h> | |||
MODULE_LICENSE("GPL"); | |||
MODULE_AUTHOR("bibble"); | |||
MODULE_DESCRIPTION("Our first module"); | |||
static int pyjama_module_init(void) { | |||
printk("Helllo world\n"); | |||
return 0; | |||
} | |||
static void pyjama_module_exit(void) { | |||
printk("Bye world\n"); | |||
} | |||
module_init(pyjama_module_init) module_exit(pyjama_module_exit) | |||
</syntaxhighlight> | |||
=Proc Filesystem= | |||
We now need to make an entry in /proc using the api in proc_fs.h. This involves | |||
*create a proc_ops entry | |||
*calling proc_create with proc_ops entry | |||
So here is the final code with the read implemented for the proc_ops | |||
<syntaxhighlight lang="c"> | |||
// Write kernel module for pyjama | |||
#include <linux/init.h> | |||
#include <linux/module.h> | |||
#include <linux/proc_fs.h> | |||
MODULE_LICENSE("GPL"); | |||
MODULE_AUTHOR("bibble"); | |||
MODULE_DESCRIPTION("Our first module"); | |||
static ssize_t pyjama_module_read(struct file *file_pointer, | |||
char *userspace_buffer, size_t count, | |||
loff_t *offset) { | |||
printk("pyjama_module_read\n"); | |||
char msg[] = "Hello from me\n"; | |||
size_t len = strlen(msg); | |||
if(*offset >=len) return 0; | |||
int result; | |||
result = copy_to_user(userspace_buffer, msg, len); | |||
*offset += len; | |||
return len; | |||
} | |||
static struct proc_dir_entry *custom_proc_dir_entry; | |||
struct proc_ops custom_proc_ops = {.proc_read = pyjama_module_read}; | |||
static int pyjama_module_init(void) { | |||
custom_proc_dir_entry = proc_create("pyjama", 0, NULL, &custom_proc_ops); | |||
if (custom_proc_dir_entry == NULL) { | |||
printk("pyjama_module_init error\n"); | |||
return -1; | |||
} | |||
printk("pyjama_module_init success\n"); | |||
return 0; | |||
} | |||
static void pyjama_module_exit(void) { | |||
proc_remove(custom_proc_dir_entry); | |||
printk("Bye world\n"); | |||
} | |||
module_init(pyjama_module_init) module_exit(pyjama_module_exit) | |||
</syntaxhighlight> |
Latest revision as of 21:58, 20 January 2025
Introduction
This seems like a way to create a VM for kernel development so thought I might take some notes
Setup Multipass
Install
snap install multipass
Create box
multipass shell
Edit /etc/ssh/sshd_config and change
KbdInteractiveAuthentication yes
Reload daemon
sudo systemctl daemon-reload
restart daemon
sudo systemctl restart ssh.service
set passwd
sudo passwd ubuntu
get IP (never knew this)
hostname -I
Setup VS Code
Go to extensions and in remote development extension. Connect via ssh
Restart Multipass
List what we have
multipass list
For this we just type
multipass shell
Install Software for Driver Development
To do this
sudo apt update sudo apt upgrade sudo apt install build-essential linux-headers-$(uname -r) kmod
Making Driver
Linux treats everything like a file and lets you do the following
- Open
- Close
- Read
- Write
- Seek
You can create a
- Char Device e.g. uart
- Block Device e.g. fs, drive
- Network Device e.g. nic
How it works
User space, talks to kernel space, using system calls. The device drivers implement, two types of systems calls, one type file operations, the other hardware management or ioctl.
Basic Module
Here is the basic set up
// Write kernel module for pyjama
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("bibble");
MODULE_DESCRIPTION("Our first module");
static int pyjama_module_init(void) {
printk("Helllo world\n");
return 0;
}
static void pyjama_module_exit(void) {
printk("Bye world\n");
}
module_init(pyjama_module_init) module_exit(pyjama_module_exit)
Proc Filesystem
We now need to make an entry in /proc using the api in proc_fs.h. This involves
- create a proc_ops entry
- calling proc_create with proc_ops entry
So here is the final code with the read implemented for the proc_ops
// Write kernel module for pyjama
#include <linux/init.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("bibble");
MODULE_DESCRIPTION("Our first module");
static ssize_t pyjama_module_read(struct file *file_pointer,
char *userspace_buffer, size_t count,
loff_t *offset) {
printk("pyjama_module_read\n");
char msg[] = "Hello from me\n";
size_t len = strlen(msg);
if(*offset >=len) return 0;
int result;
result = copy_to_user(userspace_buffer, msg, len);
*offset += len;
return len;
}
static struct proc_dir_entry *custom_proc_dir_entry;
struct proc_ops custom_proc_ops = {.proc_read = pyjama_module_read};
static int pyjama_module_init(void) {
custom_proc_dir_entry = proc_create("pyjama", 0, NULL, &custom_proc_ops);
if (custom_proc_dir_entry == NULL) {
printk("pyjama_module_init error\n");
return -1;
}
printk("pyjama_module_init success\n");
return 0;
}
static void pyjama_module_exit(void) {
proc_remove(custom_proc_dir_entry);
printk("Bye world\n");
}
module_init(pyjama_module_init) module_exit(pyjama_module_exit)