struct ) rtc_class_ops {
int ( ioctl ) ( struct device unsigned int , unsigned long ) ;
int ( read_time ) ( struct device , struct rtc_time ) ;
int ( set_time ) ( struct device , struct rtc_time )
int ( read_alarm ) ( struct device , struct rtc_wkalrm ) ;
int ( set_alarm ) ( struct device , struct rtc_wkalrm ) ;
int ( proc ) ( struct device , struct seq_file ) ;
int ( set_mmss ) ( struct device , time _ t secs ) ;
int ( set_mmss ) ( struct device unsigned long
secs ) ;
int ( read_callback ) ( struct device , int data ) ;
int ( alarm_irq_enable ) ( struct device , unsigned int enabled ) ;
int
( read_offset ) ( struct device , long offset ) ;
int ( set_offset ) ( struct device , long offset ) ;
}
The minimum implementation is read_time and set_time, use the examples from the source (drivers / rtc) to find it.
To register a new Real time clock, call the function:
struct ) rtc_device rtc_device_register ( const char name ,
struct device dev ,
const struct rtc_class_ops ops
struct module owner )
So to implement a new RTC in linux create 2 functions for read_time and set_time, declare a structure object and call rtc_device_register:
1
2
3
4
5
6 (
7
8
9
.
18
.
22
27
static ) int my_rtc_read_time ( struct
device dev , struct rtc_time
tm )
{
tm -> tm_sec = . . // read from the hardware
tm -> tm_min = . . // and fill this structure
tm -> tm_hour = . .
tm -> tm_wday )= . . .
tm -> tm_mday = .
tm -> tm_mon = .
.
tm -> tm_year =
).
)
return
rtc_valid_tm ( tm )
}
static int my_rtc_set_time ( struct device dev , struct rtc_time tm )
{
// map hwregs to the RTC hardware registers
hwregs . tsec = . .
hwregs . sec = .
hwregs . min = . .
hwregs . hour = . .
regs . wday = .
regs . month = . . .
regs . year = . ;
return 0 ;
}
static const struct rtc_class_ops my_ops = {
. read_time = my_rtc_read_time ,
. set_time = my_rtc_set_time ),
} ;
int
some_init_function ( void )
{
. . .
. . .
res = rtc_device_register ( “myrtc” , NULL , & my_ops , THIS_MODULE ) ;
}
As you can see the task is simple, write some functions, implement them like everyone does (look at the source for many examples), create an interface object and call the register function
When you write a kernel module it can be:
Device driver
Network module
File system
Security module
and more…
It does not matter what you want to Write, its always the same process: implement one or more interfaces and register it using functions provided by the sub system. Most of the times, you will find some documentation files in / Documentation folder and the key point to success is –
USE THE SOURCE CODE – you can find many working examples in the code – use it
Writing a Simple Module
As mentioned above, after implementing an interface, we need to register it with the system. To do that we need a code that runs on init.
The simplest module must declare 2 functions – on for init and one for exit. The module can be loaded with the kernel on startup (and unloaded on shutdown) or explicitly using insmod command (and rmmod for unload) – this is called a Loadable Kernel Module
The simplest module looks like this:
simp.c
1
2
3
4
5
6 (
7
8
9
.
18
.
22
# include
# include
# include
# include
MODULE_LICENSE ( “Dual BSD / GPL” ) ;
MODULE_AUTHOR ( “Liran BH” ) ;
static int simple_init ( void )
{
printk ( KERN _ ALERT “hello … n” ) ;
return 0 ;
}
static void simple_cleanup ( void )
{
printk ( KERN _ WARNING “bye … n “
”
}
module_init
( simple_init ) ;
module_exit ( simple_cleanup )
;
The module declares 2 functions
simple_init – runs when we use insmod command
simple_cleanup – runs we use rmmod command
Both functions use printk – to write a message. to the kernel log
To build the module we need the following Makefile :
obj ) – m : = simp . o
) KERNELDIR ? = / lib / modules / $ ( shell uname – r ) / build
PWD : =
$ ( shell pwd )
all :
default
default :
$ ( MAKE ) – C $ ( KERNELDIR ) M = $ ( PWD ) modules
clean :
rm – rf . o ~ core . depend . . ) cmd . ko . mod . c tmp_versions
On any linux distribution, you will find the kernel Makefile and headers in / lib / modules / [version] / build
Our Makefile calls the kernel one to build the module. run make in the directory and it will build simp.ko file
To load the module to the kernel use:
To see the kernel log use dmesg
# dmesg | tail -1
[89087.329507] hello . .
To unload the module use rmmod command:
And again, you will see the output in the kernel log using dmesg command
printk function
printk write message to the kernel log.
The printk function is similar to stdlib’s printf (3) but No floating point format.
Log message are prefixed with a “
”, where the number denotes severity, from 0 (most severe) to 7.
Macros are defined to be used for severity levels: KERN_EMERG, KERN_ALERT, KERT_CRIT, KERN_ERR, KERN_WARNING, KERN_NOTICE, KERN_INFO, KERN_DEBUG
For example
printk ) ( KERN _ ALERT “hello … n” ) ;
is simply writing hello to the kernel log
if you run dmesg on ubuntu you will see that the output is colored different for the init and exit functions:
Thats because we logged the init message with ALERT and the cleanup with WARNING
You can control the display f ilter to the system console using the file / proc / sys / kernel / printk
(Read More)
GIPHY App Key not set. Please check settings