Ioctl
This commit is contained in:
parent
04b82dab30
commit
0657191cf0
5 changed files with 143 additions and 0 deletions
11
ioctl_chardev/Makefile
Normal file
11
ioctl_chardev/Makefile
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
obj-m = my-ioctl.o
|
||||||
|
|
||||||
|
all: test.elf
|
||||||
|
make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules
|
||||||
|
|
||||||
|
clean:
|
||||||
|
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
|
||||||
|
rm test.elf
|
||||||
|
|
||||||
|
test.elf: test.c
|
||||||
|
$(CC) test.c -o test.elf
|
||||||
7
ioctl_chardev/README.txt
Normal file
7
ioctl_chardev/README.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
sudo rmmod my_ioctl
|
||||||
|
sudo insmod my_ioctl.ko
|
||||||
|
|
||||||
|
The device node is created automatically on load.
|
||||||
|
|
||||||
|
Otherwise:
|
||||||
|
sudo mknod /dev/hello c <Major> <Minor>
|
||||||
67
ioctl_chardev/my-ioctl.c
Normal file
67
ioctl_chardev/my-ioctl.c
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include "my-ioctl.h"
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Chardev Ioctl kernel module.");
|
||||||
|
MODULE_VERSION("0.0.1");
|
||||||
|
MODULE_AUTHOR("Imbus");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
#define DEVICE_NAME "hello_ioctl"
|
||||||
|
|
||||||
|
static int major; /* Dynamically assigned */
|
||||||
|
static struct class *cls;
|
||||||
|
|
||||||
|
static long my_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
|
||||||
|
|
||||||
|
/* See: https://elixir.bootlin.com/linux/v6.14.5/source/include/linux/fs.h#L2131 */
|
||||||
|
static struct file_operations fops = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.unlocked_ioctl = my_ioctl,
|
||||||
|
};
|
||||||
|
|
||||||
|
static long my_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||||
|
{
|
||||||
|
pr_info("Ioctl called by %s...\n", current->comm);
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case MY_IOCTL_FILL:
|
||||||
|
pr_info("Ioctl FILL by %s...\n", current->comm);
|
||||||
|
break;
|
||||||
|
case MY_IOCTL_WIPE:
|
||||||
|
pr_info("Ioctl WIPE by %s...\n", current->comm);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -ENOTTY; // Invalid command
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init demo_mod_init(void)
|
||||||
|
{
|
||||||
|
major = register_chrdev(0, DEVICE_NAME, &fops);
|
||||||
|
if (major < 0) {
|
||||||
|
pr_info(DEVICE_NAME " - Error registering chrdev\n");
|
||||||
|
return major;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_info(DEVICE_NAME " was assigned major number %d.\n", major);
|
||||||
|
|
||||||
|
cls = class_create(DEVICE_NAME);
|
||||||
|
device_create(cls, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);
|
||||||
|
|
||||||
|
pr_info(DEVICE_NAME " created on /dev/%s\n", DEVICE_NAME);
|
||||||
|
|
||||||
|
pr_info(DEVICE_NAME " major nbr %d loaded successfully...\n", major);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit demo_mod_exit(void)
|
||||||
|
{
|
||||||
|
device_destroy(cls, MKDEV(major, 0));
|
||||||
|
class_destroy(cls);
|
||||||
|
unregister_chrdev(major, DEVICE_NAME);
|
||||||
|
pr_info(DEVICE_NAME " unloaded successfully...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(demo_mod_init);
|
||||||
|
module_exit(demo_mod_exit);
|
||||||
18
ioctl_chardev/my-ioctl.h
Normal file
18
ioctl_chardev/my-ioctl.h
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef MY_IOCTL_H
|
||||||
|
#define MY_IOCTL_H
|
||||||
|
#include <linux/ioctl.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Crucial point here, the kernel defines a set of macros for defining IOCTL numbers:
|
||||||
|
* _IO - No command
|
||||||
|
* _IOR - Read command
|
||||||
|
* _IOW - Write command
|
||||||
|
* _IORW - RW command
|
||||||
|
* _IOC - Basis of the others
|
||||||
|
* These macros encode the data type passed to the ioctl.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MY_IOCTL_WIPE _IO('k', 0x01)
|
||||||
|
#define MY_IOCTL_FILL _IO('k', 0x02) /* Name is a placeholder, fills nothing */
|
||||||
|
|
||||||
|
#endif // MY-IOCTL_H
|
||||||
40
ioctl_chardev/test.c
Normal file
40
ioctl_chardev/test.c
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
// #include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <linux/ioctl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include "my-ioctl.h"
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
printf("I need the file to open as an argument!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = open(argv[1], O_RDWR);
|
||||||
|
if (fd < 0) {
|
||||||
|
perror("open");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctl(fd, MY_IOCTL_FILL)) {
|
||||||
|
perror("ioctl");
|
||||||
|
close(fd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctl(fd, MY_IOCTL_WIPE)) {
|
||||||
|
perror("ioctl");
|
||||||
|
close(fd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("ioctl successful\n");
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue