From 3681dbfaac2ed275380a9634c266f61ed62add56 Mon Sep 17 00:00:00 2001 From: Hizenberg469 Date: Mon, 24 Feb 2025 14:18:48 +0000 Subject: [PATCH] Character driver finished --- .vscode/settings.json | 5 ++ LKM/Makefile | 10 +++ LKM/depmod.c | 23 +++++ LKM/hello.c | 43 +++++++++ LKM/hello_func.c | 41 +++++++++ character_driver/Makefile | 8 ++ character_driver/app_test.c | 27 ++++++ character_driver/character_drivers.c | 130 +++++++++++++++++++++++++++ select_poll/multi1.c | 3 + select_poll/multi2 | Bin 16264 -> 0 bytes select_poll/multi2.c | 5 +- select_poll/poll1.c | 46 ++++++++++ 12 files changed, 340 insertions(+), 1 deletion(-) create mode 100644 .vscode/settings.json create mode 100644 LKM/Makefile create mode 100644 LKM/depmod.c create mode 100644 LKM/hello.c create mode 100644 LKM/hello_func.c create mode 100644 character_driver/Makefile create mode 100644 character_driver/app_test.c create mode 100644 character_driver/character_drivers.c delete mode 100755 select_poll/multi2 create mode 100644 select_poll/poll1.c diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..3ab5073 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "fcntl.h": "c" + } +} \ No newline at end of file diff --git a/LKM/Makefile b/LKM/Makefile new file mode 100644 index 0000000..7a05d5c --- /dev/null +++ b/LKM/Makefile @@ -0,0 +1,10 @@ +obj-m += hello.o +obj-m += hello_func.o +obj-m += depmod.o + +all: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules + +clean: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean + \ No newline at end of file diff --git a/LKM/depmod.c b/LKM/depmod.c new file mode 100644 index 0000000..065e540 --- /dev/null +++ b/LKM/depmod.c @@ -0,0 +1,23 @@ +#include // included for all kernel module +#include // included for KERN_INFO +#include // included for __init and __exit macros + + +extern void func(void); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Junet Hossain"); +MODULE_DESCRIPTION("A Simple Hello World module"); + +static int __init depmod_init(void){ + printk(KERN_INFO "In depmod_init calling exported symbol func\n"); + func(); + return 0; // Non-zero return means that the module couldn't be loaded. +} + +static void __exit depmod_cleanup(void){ + printk(KERN_INFO "Cleaning up dep module.\n"); +} + +module_init(depmod_init); +module_exit(depmod_cleanup); diff --git a/LKM/hello.c b/LKM/hello.c new file mode 100644 index 0000000..9510d47 --- /dev/null +++ b/LKM/hello.c @@ -0,0 +1,43 @@ +#include // included for all kernel module +#include // included for KERN_INFO +#include // included for __init and __exit macros + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Junet Hossain"); +MODULE_DESCRIPTION("A Simple Hello World module"); + +static int __init hello_init(void){ + printk(KERN_INFO "Hello world!\n"); + return 0; // Non-zero return means that the module couldn't be loaded. +} + +static void __exit hello_cleanup(void){ + printk(KERN_INFO "Cleaning up hello module.\n"); +} + +module_init(hello_init); +module_exit(hello_cleanup); + +/** + * Use these macros for efficient and optimized kernel modules. + * + * __init: It's a macro which is used for marking + * the function which is executed when the + * kernel is loaded. After execution, its memory + * is freed (for built-in modules). For module + * compiled as a loadable kernel module (LKM), + * __init has no effect (because the memory + * is allocated dynamically). If not used for built + * -in kernel, the memory for the init function + * remains allocated even after module initializaiton + * (wasted memory) + * + * __exit: It's a macro which is used to mark the function + * which is executed when the module is unloaded + * from the kernel. It is ignored for built-in kernel modules + * (since they can't be removed at runtime). For + * dynamically loaded modules, it ensures proper + * cleanup. If __exit is not used, the function will + * still run when removing the module, but marking + * it properly makes the code cleaner and optimized. + */ diff --git a/LKM/hello_func.c b/LKM/hello_func.c new file mode 100644 index 0000000..993662e --- /dev/null +++ b/LKM/hello_func.c @@ -0,0 +1,41 @@ +#include // included for all kernel module +#include // included for KERN_INFO +#include // included for __init and __exit macros + + +void func(void); +EXPORT_SYMBOL_GPL(func); + +/** + * EXPORT_SYMBOL_GPL: + * Since, in user space to use variable/function of one + * file to another file we use extern or header file. But + * for kernel space such thing is not allowed. But to use + * variable or function in another module/file we use + * EXPORT_SYMBOL_GPL() to export the + * function or variable to global scope for all the modules. + */ + +int val = 300; + +void func(){ + + printk(KERN_INFO"func invoked\n "); + printk(KERN_INFO" val = %d \n", val); +} + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Junet Hossain"); +MODULE_DESCRIPTION("A Simple Hello World module"); + +static int __init hello_init(void){ + printk(KERN_INFO "Init Hello func module\n"); + return 0; // Non-zero return means that the module couldn't be loaded. +} + +static void __exit hello_cleanup(void){ + printk(KERN_INFO "Cleaning up hello func module.\n"); +} + +module_init(hello_init); +module_exit(hello_cleanup); diff --git a/character_driver/Makefile b/character_driver/Makefile new file mode 100644 index 0000000..354a565 --- /dev/null +++ b/character_driver/Makefile @@ -0,0 +1,8 @@ +obj-m += character_drivers.o + +all: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules + +clean: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean + \ No newline at end of file diff --git a/character_driver/app_test.c b/character_driver/app_test.c new file mode 100644 index 0000000..2df52ad --- /dev/null +++ b/character_driver/app_test.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(){ + + int fd, i; + ssize_t ret; + char my_buf[12] = "Hello world"; + + fd = open( "/dev/demo_cdrv", O_RDWR); + if(fd < 0){ + printf("failed acquiring file descriptor return status %d\n", fd); + } + + /* Write the contents of my buffer into the device */ + ret = write(fd, my_buf, 8); + ret = read(fd, my_buf, 12); + if( ret < 0 ) + printf("read operation failed with return status %d\n", ret); + close(fd); + return 0; +} \ No newline at end of file diff --git a/character_driver/character_drivers.c b/character_driver/character_drivers.c new file mode 100644 index 0000000..eea9e80 --- /dev/null +++ b/character_driver/character_drivers.c @@ -0,0 +1,130 @@ +/* + List of printk Log Levels: + Log Level | Macro | Priority Code | Purpose + 0 | KERN_EMERG | <0> | System is unstable (panic-level message). + 1 | KERN_ALERT | <1> | Immediate action required. + 2 | KERN_CRIT | <2> | Critical errors (serious issues). + 3 | KERN_ERR | <3> | General errors (non-critical). + 4 | KERN_WARNING| <4> | Warnings (might cause issues). + 5 | KERN_NOTICE | <5> | Normal but notable conditions. + 6 | KERN_INFO | <6> | Informational messages (default for general logs). + 7 | KERN_DEBUG | <7> | Debugging messages (used for development). +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CHAR_DEV_NAME "demo_cdev" +#define MAX_LENGTH 4000 +#define SUCCESS 0 + +static char *char_device_buf; +struct cdev *demo_cdev; +dev_t mydev; //device tree as an instance + //We are using this because all character + //drivers belongs to device tree. + +static int char_dev_open(struct inode *inode, + struct file *file){ + + printk(KERN_INFO "chr_drv_dynamic :: open operation invoked \n"); + return SUCCESS; +} + +static int char_dev_release(struct inode *inode, + struct file *file){ + + printk(KERN_INFO "chr_drv_dynamic :: release opration invoked\n"); + return SUCCESS; +} + +static ssize_t char_dev_read(struct file *file, + char *buf, + size_t lbuf, + loff_t *ppos){ + + printk(KERN_INFO "chr_dev_dynamic :: read operation invoked\n"); + return 0; +} + +static ssize_t char_dev_write(struct file *file, + const char *buf, + size_t lbuf, + loff_t *ppos){ + + printk(KERN_INFO "chr_drv_dynamic :: write operation invoked \n"); + return lbuf; +} + + +/* This syntax is called "Designated initialization"*/ +/* This is allowed in C after C99*/ +static struct file_operations char_dev_fops = { + .owner = THIS_MODULE, //To define the ownership of this struct + .read = char_dev_read, //When file is read + .write = char_dev_write, //When file is written on + .open = char_dev_open, //When file is open + .release = char_dev_release //When file is closed +}; + +static int __init char_dev_init(void){ + int ret, count = 1; + + //this alloc_chrdev_region will acquire + //major number dynamically. + if(alloc_chrdev_region(&mydev, 0, count, CHAR_DEV_NAME) < 0){ + printk(KERN_ERR "failed to reserve major/minor range\n"); + return -1; + } + + //cdev_alloc function is used to allocate + //a character device. + if( !(demo_cdev = cdev_alloc())){ + printk(KERN_ERR "cdev_alloc() failed\n"); + unregister_chrdev_region(mydev, count); + return -1; + } + //It is used to initialize one + //character device allocated. + //Also to mention the capabilities + //of this character device, we also + //mention char_dev_fops. + cdev_init(demo_cdev, &char_dev_fops); + + //cdev_add is used to add character device + //to character device list. + ret = cdev_add(demo_cdev, mydev, count); + if( ret < 0 ){ + printk(KERN_INFO "Error registering device driver\n"); + cdev_del( demo_cdev ); + unregister_chrdev_region(mydev, count); + return -1; + } + printk(KERN_INFO"\nDevice Registered: %s\n", CHAR_DEV_NAME); + printk(KERN_INFO"Major number = %d, Minor number = %d\n", MAJOR (mydev), MINOR (mydev)); + + char_device_buf = (char *)kmalloc(MAX_LENGTH, GFP_KERNEL); + return 0; +} + + +static void __exit char_dev_exit(void){ + cdev_del(demo_cdev); + unregister_chrdev_region(mydev,1); + kfree(char_device_buf); + printk(KERN_INFO "\n Driver unregistered \n"); +} + +module_init(char_dev_init); +module_exit(char_dev_exit); + +MODULE_AUTHOR("Junet Hossain"); +MODULE_DESCRIPTION("Character Device Driver - Test"); +MODULE_LICENSE("GPL"); \ No newline at end of file diff --git a/select_poll/multi1.c b/select_poll/multi1.c index 25adc64..ee1bb50 100644 --- a/select_poll/multi1.c +++ b/select_poll/multi1.c @@ -18,5 +18,8 @@ int main(){ n = read( fd2, buf, 10); printf(" read data = %s from ptwo \n", buf); + + close(fd1); + close(fd2); return 0; } \ No newline at end of file diff --git a/select_poll/multi2 b/select_poll/multi2 deleted file mode 100755 index 62dda9de4d23ac3018696cf91500ce505cdcdd7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16264 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 Pe-VG!pv-kSxJ2=9IuY>E diff --git a/select_poll/multi2.c b/select_poll/multi2.c index 5203e6e..2b33a7c 100644 --- a/select_poll/multi2.c +++ b/select_poll/multi2.c @@ -20,7 +20,7 @@ int main(){ FD_ZERO(&read_set); FD_SET(fd1, &read_set); FD_SET(fd2, &read_set); - + n = select(FD_SETSIZE, &read_set, NULL, NULL, &timeout); if( n < 0 ){ perror("select "); @@ -40,6 +40,9 @@ int main(){ n = read(fd2, buf, 10); printf(" read data = %s from ptwo \n", buf); } + + // close(fd1); + // close(fd2); return 0; diff --git a/select_poll/poll1.c b/select_poll/poll1.c new file mode 100644 index 0000000..f011c4b --- /dev/null +++ b/select_poll/poll1.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(){ + int fd1, fd2; + struct pollfd pollarray[10]; + char buf[10]; + int n; + + fd1 = open("./pone", O_RDWR); + fd2 = open("./ptwo", O_RDWR); + pollarray[0].fd = fd1; + pollarray[1].fd = fd2; + pollarray[0].events = POLLIN; + pollarray[1].events = POLLIN; + + n = poll(pollarray, 2, 10000); + if(n < 0){ + perror("poll:"); + exit(1); + } + + //test whether fd1 is ready or not + if( (pollarray[0].revents & POLLIN)){ + printf(" reading from fd1 (pone)\n"); + n = read(fd1, buf, 10); + printf(" read data = %s from pone\n", buf); + } + + + //test whether fd2 is ready or not + if( (pollarray[1].revents & POLLIN)){ + printf(" reading from fd2 (ptwo)\n"); + n = read(fd2, buf, 10); + printf(" read data = %s from ptwo\n", buf); + } + + // close(fd1); + // close(fd2); + return 0; +} \ No newline at end of file