0% found this document useful (0 votes)
13 views

Kernel Programming

Kernel programing

Uploaded by

2023ht01513
Copyright
© © All Rights Reserved
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views

Kernel Programming

Kernel programing

Uploaded by

2023ht01513
Copyright
© © All Rights Reserved
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 60

Linux Kernel Module

Programming
Anandkumar
June 5, 2021

Anandkumar 1
Agenda
• Introduction
• Review Standard Functions
• Setup Environment
• User mode Linux
• Qemu Setup
• Write example1
• Compiling Modules
• Handling Runtime Parameters
Anandkumar 2
Agenda cont…
• More Kernel Macros
• Write example2
• Jiffies
• Working with multiple files
• Dependency in Driver
• Character Driver

Anandkumar 3
Introduction
• Similar to Java Servlets with predefined
structure and function names
• Code that executes as part of the Linux
kernel
• Extends the capabilities and sometimes
might modify the behavior of the kernel

Anandkumar 4
Introduction Cont…
• Common C functions are not available to
modules (such as printf, scanf, strcat, or
system)
• Instead you must use kernel defined
functions (/proc/ksyms)

Anandkumar 5
What Is the Kernel?

Anandkumar 6
UserSpace Vs KernelSpace
• The Concept of kernel space and user space is all about
memory and access rights.
• It is a feature of modern CPU, allowing it to operate
either in privileged or unprivileged mode.
• One ,may consider kernel to be privileged and user
apps are restricted.

Anandkumar 7
UserSpace Vs KernelSpace
cont…

Anandkumar 8
Split view of kernel…

Anandkumar 9
Classification of Drivers

Anandkumar 10
Anandkumar 11
Anandkumar 12
Standard Functions
• printk ()
– 8 Priority Levels: KERN_WARNING, KERN_ALERT
– Kernel modules cannot call any functions in the C
runtime library (e.g., ‘printf()’)
– But similar kernel versions of important functions are
provided (e.g., ‘printk()’)
– Syntax and semantics are slightly different (e.g.,
priority and message-destination)
– Capabilities may be somewhat restricted (e.g., printk()
can’t show floating-point)

Anandkumar 13
Standard Functions cont…
• Init function sets up variables, tells the kernel what the
module provides and registers any necessary functions
• Cleanup function undoes changes made by init

Anandkumar 14
Anandkumar 15
Standard Functions Cont…
• int init_module(void)
 Called when the kernel loads your module.
 Initialize all your stuff here.
 Return 0 if all went well, negative if something blew
up.
• void cleanup_module(void)
 Called when the kernel unloads your module.
 Free all your resources here.

Anandkumar 16
A minimal module-template
#include <linux/module.h>
int init_module( void )
{
// code here gets called during module installation
}
void cleanup_module( void )
{
// code here gets called during module removal
}
MODULE_LICENSE(“GPL”);
Setup Environment
• Install Kernel Module Tools
# sudo apt-get install kmod
• Install development tools and kernel headers
# sudo apt-get install build-essential
# sudo apt-get install linux-headers-$(uname -r)

Anandkumar 18
User-Mode Linux
• What is User-Model Linux?
– Ported to run itself as a set of Linux
(non-root user) process on itself.
– Short form as UML
– UML started by Jeff Dike since Feb
1999
– Use simulated hardware i.e., services
provided by host kernel.
– Run (nearly) all applications and
services available on the host
architecture.
User-Mode Linux
– Provides a self-contained environment:
• Identical as hosting Linux kernel,
• Processes have no access to host resources that were not
explicitly provided
– Layer diagram:
ls ps netscape

G eneral kernel
U ser-m ode
ls ps netscape D rivers
arch

G eneral kernel

A rchitecture Layer D rivers

H ardw are - C P U , disks, netw ork, term inals, ...


Anandkumar
User-Mode Linux
• All UML devices are virtual; constructed from the
abstractions provided by the host kernel.
• The UML devices:
– Consoles and serial lines
• Main console, virtual console and serial lines.
– Block devices
• Access to anything on the host which can be mounted, e.g.
CDROM, disk partition
– Network devices
• Network access between UML to host OS/UML and between UML to
host in outside network.

Anandkumar
User-Mode Linux
• Focus of the presentation:
– Applications
– Design and Implementation
– Some mentioned future works

Anandkumar
User-Mode Linux
Applications
• Kernel debugging
– on top of software OS, not on separate test machine.
– standard suite of process debugging tools such as gdb,
gcov and gprof can be utilized.
• Prototyping
– Realizing virtual network with a single physical network.
– Testing software configuration.

Anandkumar
User-Mode Linux
Applications
• Isolation
– separating users/applications of virtual machines from
each other and from the host.
– purposes:
• Against possibly hostile/untrusted processes,
• performance control - allocation of resources (e.g. CPU,
memory, disk space), avoidance of race
• Multiple environments
– Especially for Linux applications, some incompatibility
problems may exists and need to test.
• A Linux environment for other operating systems
– Many Linux applications are free and open-source. With
UML, those applications can run upon other hosting OS
like MS Windows.
Anandkumar
User-Mode Linux
Setup
• Install Dependency
# sudo apt-get install build-essential flex bison
# sudo apt-get install xz-utils wget
# sudo apt-get install ca-certificates bc
# sudo apt-get install libncurses-dev

• Downloading the Kernel and extract


www.kernel.org
# tar -xvzf linux-5.1.16.tar.gz

Anandkumar
User-Mode Linux
Setup
• Configuring the Kernel
# make ARCH=um menuconfig

Anandkumar
User-Mode Linux
Setup
• Build Kernel
# make ARCH=um
# mkdir ../bin
# cd ../bin
# cp ../linux-5.1.16/linux .
• Setup Guest file system
# tar –xvzf alpine-rootfs.tgz
• Boot system
# ./bin/linux rootfstype=hostfs
rootflags=/home/test/uml/rootfs/ rw mem=64M
init=/bin/sh

Anandkumar
Rootfs

Anandkumar
User-Mode Linux
Setup with custom rootfs
• Download busybox and untar
https://busybox.net/downloads/busybox-
1.33.1.tar.bz2
# tar –xvjf busybox-1.33.1.tar.bz2

• Configure Busybox
# make menuconfig
Enable static build option
• Build Busybox
# make

Anandkumar
User-Mode Linux
Setup with custom rootfs
• Install Busybox
# make install
• Using this rootfs to boot
# ./bin/linux rootfstype=hostfs
rootflags=/home/test/uml/rootfs_busybox/ rw
mem=64M init=/bin/sh

Anandkumar
Qemu Setup
• Install Dependency
# sudo apt-get install qemu-system

• Download Cross compiler and install it


# tar -xvf gcc-linaro-10.2.1-2021.02-x86_64_arm-
linux-gnueabihf.tar.xz

• Downloading the Kernel and extract


www.kernel.org
# tar -xvzf linux-5.1.16.tar.gz

Anandkumar
Qemu Setup
• Copy the default configuration file
#cp arch/arm/configs/vexpress_defconfig .config

• Configuring the Kernel


# make ARCH=arm menuconfig

• Cross compile Kernel


# make ARCH=arm
CROSS_COMPILE=/home/test/qemu/gcc-linaro-10.2.1-
2021.02-x86_64_arm-linux-gnueabihf/bin/arm-linux-
gnueabihf-

Anandkumar
Qemu Setup
• Boot
# qemu-system-arm -M vexpress-a9 -kernel
vmlinuz-3.2.0-4-vexpress -initrd initrd.img-3.2.0-
4-vexpress -drive
if=sd,file=debian_wheezy_armhf_standard.qcow
2 -append "root=/dev/mmcblk0p2"

Anandkumar
Kernel module command
• lsmod
List Modules that Loaded Already
• insmod
Insert Module into Kernel
• modinfo
Display Module Info
• rmmod
Remove Module from Kernel
• modprobe
Add or Remove modules from the kernel
Anandkumar 34
Example1
/* example1.c - The simplest kernel module. */
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_ALERT */
#include <linux/init.h> /* Needed for macros */

int example1_init(void) {
printk(KERN_ALERT "Initing example1\n"); /* A non 0 return means
init_module failed; module can't be loaded. */
return 0;
}

void example1_stop(void) {
printk(KERN_ALERT "Unloading example1\n");
}

module_init (example1_init);
module_exit (example1_stop);

Anandkumar 35
Example 1 cont…
• Accompany your module with a 1-line GNU
Makefile:
 obj-m += example1.o
• Run the magic make command:
 make -C /lib/modules/$(uname -r)/build M=$(pwd)
modulesProduces: example1.ko

• To manually load your module:


 insmod example1.ko
• Where’s our message?
 dmesg
• To unload your module:
 rmmod example1

Anandkumar 36
Handling Runtime Parameters

• module_param() ,
module_param_array() and
module_param_string().
The macro takes 3 arguments: the name of the variable, its
type and permissions for the corresponding file in sysfs.

Anandkumar 37
More Kernel Macros
• MODULE_LICENSE ()
• MODULE_AUTHOR ()
• MODULE_DESCRIPTION ()
• MODULE_SUPPORTED_DEVICE ()

Anandkumar 38
Example 2
/*
* example2.c - Demonstrates command line argument passing to
* a module.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/stat.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("test");
MODULE_DESCRIPTION ("A module to teach module writing");
MODULE_SUPPORTED_DEVICE ("The mind");

static short int myshort = 1;


static int myint = 420;
Anandkumar 39
Example 2
static long int mylong = 9999;
static char *mystring = "blah";
static int myintArray[2] = { -1, -1 };

/*
* module_param(foo, int, 0000)
* The first param is the parameters name
* The second param is it's data type
* The final argument is the permissions bits,
* for exposing parameters in sysfs (if non-zero) at a later
* stage.
*/
module_param(myshort, short, S_IRUSR | S_IWUSR | S_IRGRP |
S_IWGRP);
MODULE_PARM_DESC(myshort, "A short integer");
module_param(myint, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);

Anandkumar 40
Example 2
MODULE_PARM_DESC(myint, "An integer");
module_param(mylong, long, S_IRUSR);
MODULE_PARM_DESC(mylong, "A long integer");
module_param(mystring, charp, 0000);
MODULE_PARM_DESC(mystring, "A character string");
static int arr_argc = 0;

module_param_array(myintArray, int, &arr_argc, 0000);


MODULE_PARM_DESC(myintArray, "An array of integers");

Anandkumar 41
Example 2
static int __init example2_init(void)
{
int i;
printk(KERN_INFO "Entering Example2\n=============\n");
printk(KERN_INFO "myshort is a short integer: %hd\n", myshort);
printk(KERN_INFO "myint is an integer: %d\n", myint);
printk(KERN_INFO "mylong is a long integer: %ld\n", mylong);
printk(KERN_INFO "mystring is a string: %s\n", mystring);
for (i = 0; i < (sizeof myintArray / sizeof (int)); i++)
{
printk(KERN_INFO "myintArray[%d] = %d\n", i, myintArray[i]);
}
printk(KERN_INFO "got %d arguments for myintArray.\n", arr_argc);
return 0;
}

Anandkumar 42
Example 2
static void __exit example2_exit(void)
{
printk(KERN_INFO "Exiting Example2\n");
}

module_init(example2_init);
module_exit(example2_exit);

Anandkumar 43
Module v0.2 cont..

Try to compile on your own and run it??

Anandkumar 44
Example 2 cont…
• Accompany your module with a 1-line GNU
Makefile:
 obj-m += example2.o
• Run the magic make command:
 make -C /lib/modules/$(uname -r)/build M=$(pwd)
modulesProduces: example2.ko

• To manually load your module:


 insmod example2.ko
• Where’s our message?
 dmesg
• To unload your module:
 rmmod example2

Anandkumar 45
jiffies
• unsigned long volatile jiffies;
• global kernel variable (used by scheduler)
• Initialized to zero when system reboots
• Gets incremented when timer interrupts
• So it counts ‘clock-ticks’ since cpu restart
• ‘tick-frequency’ is architecture dependent
jiffies
• Write kernel module to display jiffies value
on installation of kernel module?
jiffies
/*
* example_jiffies.c
*/
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/jiffies.h>

int init_module(void)
{
printk(KERN_INFO "Entering Jiffies Example\n");
printk(KERN_INFO "The jiffies value=%ld\n",jiffies);

return 0;
}

void cleanup_module(void)
{
printk(KERN_INFO "Exiting Jiffies Example\n");
}
Jiffies cont…
• Accompany your module with a 1-line GNU
Makefile:
 obj-m += example_jiffies.o
• Run the magic make command:
 make -C /lib/modules/$(uname -r)/build M=$(pwd)
modulesProduces: example_jiffies.ko

• To manually load your module:


 insmod example_jiffies.ko
• Where’s our message?
 dmesg
• To unload your module:
 rmmod example_jiffies

Anandkumar 49
Working with multiple files
/* file1.c - The simplest kernel module. */
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_ALERT */
#include <linux/init.h> /* Needed for macros */

int example1_init(void) {
printk(KERN_ALERT "Initing example1\n"); /* A non 0 return means
init_module failed; module can't be loaded. */
return 0;
}

module_init (example1_init);
Working with multiple files
/* file2.c - The simplest kernel module. */
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_ALERT */
#include <linux/init.h> /* Needed for macros */

void example1_stop(void) {
printk(KERN_ALERT "Exiting example1\n");
}

module_exit (example1_stop);
Working with multiple files
• Sources exists in two files file1.c and file2.c
obj-m += multiple.o
multiple-objs += file1.o file2.o
Dependency between modules
/* dep1.c - The simplest kernel module. */
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_ALERT */
#include <linux/init.h> /* Needed for macros */

void dep1_func(void){
printk(KERN_INFO "I am in dep1 func\n");
}

int dep1_init(void) {
printk(KERN_INFO "Initing dep1\n"); /* A non 0 return means init_module failed; module can't be loaded. */
return 0;
}

void dep1_stop(void) {
printk(KERN_INFO "Exiting dep1\n");
}

module_init (dep1_init);
module_exit (dep1_stop);
EXPORT_SYMBOL(dep1_func);
Dependency between modules
/* dep2.c - The simplest kernel module. */
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_ALERT */
#include <linux/init.h> /* Needed for macros */

extern void dep1_func(void);

int dep2_init(void) {
printk(KERN_INFO "Initing dep2\n"); /* A non 0 return means init_module failed; module can't be loaded. */
dep1_func();
return 0;
}

void dep2_stop(void) {
printk(KERN_INFO "Exiting dep2\n");
}

module_init (dep2_init);
module_exit (dep2_stop);
Dependency between modules
• Accompany your module with a 2-line GNU Makefile:
 obj-m += dep1.o
obj-m += dep2.o
• Run the magic make command:
 make -C /lib/modules/$(uname -r)/build M=$(pwd)
modulesProduces: dep1.ko,dep2.ko

• Copy module to /lib/modules/5.8.0-55-generic/


manually:
 cp dep1.ko dep2.ko /lib/modules/5.8.0-55-generic/
• Run depmod
 Depmod -a
• To insert module:
 Modprobe dep2
• To remove module:
 Modprobe –r dep2

Anandkumar 55
Character Driver
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>

#define DEVICE_NAME "testchar"


static int num_major;

static int test_open(struct inode *inode, struct file *file)


{
printk(KERN_INFO "test_open called\n");
return 0;
}

static int test_release(struct inode *inode, struct file *file)


{
printk(KERN_INFO "test_release called\n");
return 0;
}
Character Driver
static ssize_t test_read(struct file *filp,
char *buf,
size_t len,
loff_t * off)
{
printk(KERN_INFO "test_read called\n");
return 0;
}

static ssize_t test_write(struct file *filp,


const char *buf,
size_t len,
loff_t * off)
{

printk(KERN_INFO "test_write called\n");


return 0;
}
Character Driver
static struct file_operations fops= {
.open = test_open,
.release = test_release,
.read = test_read,
.write = test_write,
};

static int __init test_init(void)


{

printk(KERN_INFO "Entering Test Character Driver \n");

num_major=register_chrdev(0, DEVICE_NAME, &fops);


printk(KERN_INFO "Major Number = %d \n",num_major);
printk(KERN_INFO "Name = %s \n",DEVICE_NAME);
printk(KERN_INFO "Generate the device file with\
mknod /dev/%s c %d 0 \n",DEVICE_NAME,num_major);

return 0 ;

}
Character Driver
static void __exit test_cleanup(void)
{
unregister_chrdev(num_major, DEVICE_NAME);
printk(KERN_INFO "Exiting Test Character Driver \n");
}

module_init(test_init);
module_exit(test_cleanup);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("test");
MODULE_DESCRIPTION("Character Device Driver");
MODULE_SUPPORTED_DEVICE("testchar");
Character Driver
• Accompany your module with a 1-line GNU
Makefile:
 obj-m += example_character.o
• Run the magic make command:
 make -C /lib/modules/$(uname -r)/build M=$(pwd)
modulesProduces: example_character.ko

• To manually load your module:


 insmod example_character.ko
• Where’s our message?
 dmesg
• To unload your module:
 rmmod example_character
• Test Driver functionality using shell command:

Anandkumar 60

You might also like