How to find execution time in kernel space [duplicate] - c

This question already has answers here:
How can i print current time in kernel?
(2 answers)
Closed 1 year ago.
I want to find the execution time of a kernel level thread in linux kernel version 5.11.0. the program is in C and I am using do_gettimeofday function for the same.
code: a C file named task-1.c
//to create kernel level threads and measure the time of completion
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/time.h>
#include <linux/init.h>
#include <linux/times.h>
#include <linux/delay.h>
static struct task_struct *thread_st;
int thread_fn(void *i) // Function executed by kernel thread
{
printk(KERN_INFO "In thread1");
return 0;
}
// Module Initialization
static int __init init_thread(void)
{
struct timeval t0,t1;
double temp;
//for calculating time take to create a thread
do_gettimeofday(&t0,NULL);
printk(KERN_INFO "Creating Thread\n");
thread_st = kthread_run(thread_fn, NULL, "mythread1003");
do_gettimeofday(&t1, NULL);
if (thread_st)
{
temp = ((t1.tv_sec - t0.tv_sec)*1000000 + (t1.tv_usec -
t0.tv_usec));
printk(KERN_INFO "Thread (Name: mythread1003) Created successfully and Time Take (to create thread is ) %.2f \n",temp);
}
else
printk(KERN_ERR "Thread creation failed\n");
return 0;
}
// Module Exit
static void __exit cleanup_thread(void)
{
printk(KERN_INFO "Cleaning Up\n");
if (thread_st)
{
kthread_stop(thread_st);
printk(KERN_INFO "Thread stopped");
}
}
MODULE_LICENSE("GPL");
MODULE_AUTHOR("xyz");
MODULE_DESCRIPTION("A Simple Module for the k.threads");
module_init(init_thread);
module_exit(cleanup_thread);
Makefile:
obj-m += task-1.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
but when I am trying to execute the above using make command it give me the following error
make -C /lib/modules/5.11.0/build M=/home/jayant/Desktop/cse2005/lab-7-kernel-threads/TASK-1 modules
make[1]: Entering directory '/home/jayant/Downloads/linux-5.11'
CC [M] /home/jayant/Desktop/cse2005/lab-7-kernel-threads/TASK-1/task-1.o
/home/jayant/Desktop/cse2005/lab-7-kernel-threads/TASK-1/task-1.c: In function ‘init_thread’:
/home/jayant/Desktop/cse2005/lab-7-kernel-threads/TASK-1/task-1.c:21:20: error: storage size of ‘t0’ isn’t known
struct timeval t0,t1;
^~
/home/jayant/Desktop/cse2005/lab-7-kernel-threads/TASK-1/task-1.c:21:23: error: storage size of ‘t1’ isn’t known
struct timeval t0,t1;
^~
/home/jayant/Desktop/cse2005/lab-7-kernel-threads/TASK-1/task-1.c:25:5: error: implicit declaration of function ‘do_gettimeofday’; did you mean ‘do_settimeofday64’? [-Werror=implicit-function-declaration]
do_gettimeofday(&t0,NULL);
^~~~~~~~~~~~~~~
do_settimeofday64
/home/jayant/Desktop/cse2005/lab-7-kernel-threads/TASK-1/task-1.c:21:23: warning: unused variable ‘t1’ [-Wunused-variable]
struct timeval t0,t1;
^~
/home/jayant/Desktop/cse2005/lab-7-kernel-threads/TASK-1/task-1.c:21:20: warning: unused variable ‘t0’ [-Wunused-variable]
struct timeval t0,t1;
^~
cc1: some warnings being treated as errors
scripts/Makefile.build:279: recipe for target '/home/jayant/Desktop/cse2005/lab-7-kernel-threads/TASK-1/task-1.o' failed
make[2]: *** [/home/jayant/Desktop/cse2005/lab-7-kernel-threads/TASK-1/task-1.o] Error 1
Makefile:1800: recipe for target '/home/jayant/Desktop/cse2005/lab-7-kernel-threads/TASK-1' failed
make[1]: *** [/home/jayant/Desktop/cse2005/lab-7-kernel-threads/TASK-1] Error 2
make[1]: Leaving directory '/home/jayant/Downloads/linux-5.11'
Makefile:3: recipe for target 'all' failed
make: *** [all] Error 2
what I think is that, the problem is with do_gettimeofday command. Is there any other way to calculate the execution time of kernel level thread also I tried using clock() but still couldn't find the solution for the same.

In kernel you can use jiffies (http://books.gigatux.nl/mirror/kerneldevelopment/0672327201/ch10lev1sec3.html) to measure time lapses http://www.makelinux.net/ldd3/chp-7-sect-1.shtml - 7.1. Measuring Time Lapses
Are you using Yocto or Bitbake directly ?

Related

Why my program is failing with "dereferencing pointer to incomplete type ‘struct kmem_cache’

Trying to understand Linux slab allocator internals. But unable to dereference struct kmem_cache structure. Dont know what wrong I am doing here. I might be very silly coding bug (sorry for that) or some deep concept which I dont know. I thought it would be really easy to print fields of struct kmem_cache. My intention was to access its "list" field. But not even able to print its name.
I tried to dig deeper in source tree, to see if struct kmem_cache is of typedef (as mentioned in this post : dereferencing Pointer to incomplete type struct) , but no it is simple structure.
crash> kmem_cache
kmem_cache = $1 = (struct kmem_cache *) 0xffff9fdac0002000
crash> struct kmem_cache
struct kmem_cache {
struct kmem_cache_cpu *cpu_slab;
slab_flags_t flags;
unsigned long min_partial;
unsigned int size;
...
Linux 5.4.0-135-generic #152-Ubuntu SMP Wed Nov 23 20:19:22 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
Source : kmem_cache.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
typedef struct {
int a;
int b;
} mytype_t;
static mytype_t *obj;
static struct kmem_cache *s_cache;
static int __init
start(
void)
{
s_cache = kmem_cache_create("SAMPLE_CACHE", sizeof (mytype_t), 0, SLAB_POISON, NULL);
if (!s_cache) {
printk(KERN_ERR "kmem_cache_create failed.\n");
return -ENOMEM;
}
obj = kmem_cache_alloc(s_cache, 0);
if (!obj) {
printk(KERN_ERR "kmem_cache_alloc failed.\n");
return -ENOMEM;
}
printk(KERN_INFO "(%x) (%x)\n", obj->a, obj->b);
printk(KERN_INFO "cache name : %s\n", s_cache->name);
return 0;
}
static void __exit
end(
void)
{
kmem_cache_free(s_cache, obj);
kmem_cache_destroy(s_cache);
return;
}
module_init(start);
module_exit(end);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Unknown");
Makefile
obj-m := kmem_cache.o
KDIR := /lib/modules/$(shell uname -r)/build/
all:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean
Compilation error:
# make
make -C /lib/modules/5.4.0-135-generic/build/ M=/root/ldd/slab/kmem_cache modules
make[1]: Entering directory '/usr/src/linux-headers-5.4.0-135-generic'
CC [M] /root/ldd/slab/kmem_cache/kmem_cache.o
/root/ldd/slab/kmem_cache/kmem_cache.c: In function ‘start’:
/root/ldd/slab/kmem_cache/kmem_cache.c:29:47: error: dereferencing pointer to incomplete type ‘struct kmem_cache’
29 | printk(KERN_INFO "cache name : %s\n", s_cache->name);
| ^~
make[2]: *** [scripts/Makefile.build:270: /root/ldd/slab/kmem_cache/kmem_cache.o] Error 1
make[1]: *** [Makefile:1765: /root/ldd/slab/kmem_cache] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-5.4.0-135-generic'
make: *** [Makefile:6: all] Error 2

Attempting to load module, however when trying to compile the module the computer states that several structs are undefined

The purpose of this module is to basically do the same thing as what happens when you type into your linux command line cat /proc/buddyinfo
Code
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mmzone.h>
#define DRIVER_AUTHOR "Matthew James Barnes <mbarnes2k5#Gmail.com>"
#define DRIVER_DESC "A driver that does the same thing as /proc/buddyinfo"
/***
*GLOBAL VARIABLES
***/
extern struct pglist_data *first_online_pgdat(void);
extern struct pglist_data *next_online_pgdat(struct pglist_data*pgdat);
struct pglist_data *pgdat;
extern struct zone *zone;
int init_module(void)
{
int order;
for(pgdat = first_online_pgdat(); pgdat; pgdat = next_online_pgdat(pgdat))
{
for(zone = pgdat->node_zones; zone; zone = next_zone(zone)){
printk(KERN_INFO "Node %d, zone %8s ",pgdat->node_id, zone->name);
printk(KERN_INFO "Node %d", pgdat->node_id);
printk(KERN_CONT "Zone %s",zone->name);
for( order = 0; order < MAX_ORDER; ++order)
printk(KERN_CONT "%6lu ", zone->free_area[order].nr_free);
printk(KERN_CONT "\n");
}
}
return 0;
}
void cleanup_module(void){
printk(KERN_INFO "Zones have been feenished.\n");
}
MODULE_LICENSE("GPL");
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
~
~
~
~
~
~
~
I decided to go lean and create a makefile as well as a folder within my kernel called module-edits.
In module edits when I run the makefile, I run into a compilation error.
The command line returns the following:
make -C /lib/modules/5.4.0-26-generic/build M=/usr/local/share/source_code/version1/module-edits modules
make[1]: Entering directory '/usr/src/linux-headers-5.4.0-26-generic'
Building modules, stage 2.
MODPOST 1 modules
ERROR: "next_online_pgdat" [/usr/local/share/source_code/version1/module-edits/printbuddy.ko] undefined!
ERROR: "next_zone" [/usr/local/share/source_code/version1/module-edits/printbuddy.ko] undefined!
ERROR: "zone" [/usr/local/share/source_code/version1/module-edits/printbuddy.ko] undefined!
ERROR: "first_online_pgdat" [/usr/local/share/source_code/version1/module-edits/printbuddy.ko] undefined!
make[2]: [scripts/Makefile.modpost:94: __modpost] Error 1
make[1]: [Makefile:1632: modules] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-5.4.0-26-generic'
make: [makefile:5: all] Error 2
Now, what is baffling about this is that when I typed
#include <linux/mmzone.h>
there are a number of structs.
pgdat is a struct that allows access to the current page data.
*first_online_pgdat(void); is a function that points to the first page.
*next_online_pgdat(struct pglist_data*pgdat); points to the next page.
struct pglist_data *pgdat;
is basically the representation of my page.
and extern struct zone *zone is the representation of the zone type of the pages.
All of this is included in mmzone, but it's as if the functions in mmzone.h are not even being referenced.
I don't really understand what is going on, but I would appreciate assistance from experienced linux programmers.

creating a simple kernel module using VirtualBox which outputs the elements of a C struct

I am attempting to create a simple kernel module using Oracle VirtualBox. The module simply instantiates instances of a C struct and outputs the elements of those struct instances using a printk statement. The problem is that I am getting no output of the elements of my struct instances
the make file code is as follows:
obj-m += simple.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=S(PWD) clean
the companion file is named simple.c and is as follows:
#include<linux/init.h>
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/list.h>
#include<linux/types.h>
struct birthday{
int day;
int month;
int year;
struct list_head list;
}
//defines and initializes the variable birthday_list of type struct list_head
static LIST_HEAD(birthday_list);
//create and initialize instances of struct birthday
struct birthday *person2;
person2 = kmalloc(sizeof(*person2), GFP_KERNEL);
person2->day = 11;
person2->month = 9;
person2->year = 1985;
INIT_LIST_HEAD(&person2->list);
//this function is called when the module is loaded
int simple_init(void){
printk(KERN_INFO "Loading Module\n");
printk(KERN_INFO "Person 2 day is: %d \n", person2->day);
printk(KERN_INFO "Person 2 month is: %d \n", person2->month);
printk(KERN_INFO "person 2 year is: %d \n", person2->year);
return 0;
}
//this function is called when the module is removed
int simple_exit(void){
printk(KERN_INFO "Removing module\n");
}
//macros for registering module entry and exit points
module_init(simple_init);
module_exit(siple_exit);
}
The problem is that the only output I am getting is the first print statement "Loading Module", the other print statements which are supposed to output the elements of the instance of my struct do not output anything at all. Is something wrong with my syntax?
The procedure I am using, is:
type, on the command line, the command: "make" in order to compile the file simple.c
Next, type the command: "sudo insmod simple.ko" to load the kernel module.
Next, type the command: "dmesg" to see the output of my printk statements.
When I follow this procedure, the only output I get is: "Loading Module" I get no output from the instance of my struct

Strange printk effect on linux stack size testing

I am trying to test linux kernel stack size in 64 bit.
I found this weird behaviour.
I wrote following code to crash the kernel but strange thing is that
it crashes only if printk is uncommented,
otherwise runs fine with no errors/warnings!!.
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
static int __init crash_stack_init(void)
{
long arr[1024];
long *a;
a = &arr[0];
//printk("%p\n", &arr[0]);
return 0;
}
enter code here
static void __exit crash_stack_exit(void)
{
}
module_init(crash_stack_init);
module_exit(crash_stack_exit);
Here is the "make" output without the printk,
make -C /lib/modules/4.4.0-53-generic/build
M=/home/naveenvc/work/ker/crash_stack modules
make[1]: Entering directory '/usr/src/linux-headers-4.4.0-53-generic'
CC [M] /home/naveenvc/work/ker/crash_stack/crash_stack.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/naveenvc/work/ker/crash_stack/crash_stack.mod.o
LD [M] /home/naveenvc/work/ker/crash_stack/crash_stack.ko
make[1]: Leaving directory '/usr/src/linux-headers-4.4.0-53-generic'
And make output with printk,
make -C /lib/modules/4.4.0-53-generic/build
M=/home/naveenvc/work/ker/crash_stack modules make[1]: Entering
directory '/usr/src/linux-headers-4.4.0-53-generic' CC [M]
/home/naveenvc/work/ker/crash_stack/crash_stack.o
> /home/naveenvc/work/ker/crash_stack/crash_stack.c: In function
‘crash_stack_init’:
/home/naveenvc/work/ker/crash_stack/crash_stack.c:14:1: warning: the
frame size of 8200 bytes is larger than 1024 bytes
[-Wframe-larger-than=] } ^
Building modules, stage 2. MODPOST 1
modules CC
/home/naveenvc/work/ker/crash_stack/crash_stack.mod.o LD [M]
/home/naveenvc/work/ker/crash_stack/crash_stack.ko make[1]: Leaving
directory '/usr/src/linux-headers-4.4.0-53-generic'
What could be causing this?
The stack size is well documented and the above is not the right way to test, in particular in older kernels which used hugepages to back the stack the aforementioned code would jump over to the next stack.
The func __crash_stack_init with prink commented out is a leaf function - it does not call anything, so the compiler knows exactly what happens with local vars. In particular in this code it sees the full array is not needed and thus its not being allocated. However, the call to printk passes arr in. The compiler does not know what the func is going to do with it, thus it has to reserve 1024 * sizeof(long) on the stack which results in the warning.
Stacks got bumped to 16KB years ago, you can start reading here https://lwn.net/Articles/600644/

Undefined functions while compiling linux kernel module

I am trying to work with linux softirq. A have a simple program that uses linux system calls defined in linux/interrupt.h:
//
// Created by kivi on 24.09.16.
//
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/stat.h>
#define SHARED_IRQ 17
static int irq = SHARED_IRQ, my_dev_id, irq_counter = 0;
module_param( irq, int, S_IRUGO );
/* The interrupt handler */
static irqreturn_t xxx_interrupt( int irq, void *dev_id ) {
printk( KERN_INFO "In the top-half: counter = %d\n", irq_counter );
raise_softirq( XXX_SOFT_IRQ );
return IRQ_HANDLED;
}
/* The bottom half */
void xxx_analyze(struct softirq_action *str) {
irq_counter++;
printk( KERN_INFO "In the bottom-half: counter = %d\n", irq_counter );
}
static int __init my_init( void ) {
request_irq( irq, xxx_interrupt, 0, "xxx", NULL );
open_softirq( XXX_SOFT_IRQ, xxx_analyze);
printk( KERN_INFO "Successfully set softirq handler on IRQ %d\n", irq );
return 0;
}
static void __exit my_exit( void ) {
synchronize_irq( irq );
free_irq( irq, &my_dev_id );
printk( KERN_INFO "Successfully unloading, irq_counter = %d\n", irq_counter );
}
module_init( my_init );
module_exit( my_exit );
MODULE_LICENSE( "GPL v2" );
When I try to compile this module I get linker errors that functions open_softirq() and raise_softirq() are not defined:
kivi#kivi-pc:~/sp_labs/irq_exc/softirq$ make
make -C /lib/modules/4.7.5-custom/build M=/home/kivi/sp_labs/irq_exc/softirq modules
make[1]: Entering directory '/home/kivi/Downloads/linux-4.7.5'
Building modules, stage 2.
MODPOST 1 modules
WARNING: "open_softirq" [/home/kivi/sp_labs/irq_exc/softirq/softirq.ko] undefined!
WARNING: "raise_softirq" [/home/kivi/sp_labs/irq_exc/softirq/softirq.ko] undefined!
make[1]: Leaving directory '/home/kivi/Downloads/linux-4.7.5'
The interesting thing is that functions request_irq() e.t.c. are also defined in interrupt.h file, but they don't cause any problem.
Here is my Makefile:
obj-m += softirq.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
So can anyone help me please with my problem.
P.S. i googled my problem and found some advice that I should add KBUILD_EXTRA_SYMBOLS=*module path*/Module.symvers when compiling, but it didn't help.
The problem is that the open_softirq and raise_softirq functions are not exported, and so you cannot link to them. Exported functions are marked with the EXPORT_SYMBOL or EXPORT_SYMBOL_GPL macros.
On the other side, you will see how request_irq is exported (actually, it is inlined to request_threaded_irq, which is exported).
You can find plenty of information about the EXPORT_SYMBOL macros. For instance, here's an explanation from Robert Love.
Now, you are probably wondering why those functions aren't exported. Well, softirqs are a low-level mechanism, meant to be used by other higher-level facilities, so the intention is to prevent its usage in non-core kernel code.
Modules should use higher-level facilities instead (timers for instance).
It is interesting to check how many softirqs users the kernel has.
$ git grep open_softirq
block/blk-softirq.c: open_softirq(BLOCK_SOFTIRQ, blk_done_softirq);
include/linux/interrupt.h:extern void open_softirq(int nr, void (*action)(struct softirq_action *));
kernel/rcu/tiny.c: open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
kernel/rcu/tree.c: open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
kernel/sched/fair.c: open_softirq(SCHED_SOFTIRQ, run_rebalance_domains);
kernel/softirq.c:void open_softirq(int nr, void (*action)(struct softirq_action *))
kernel/softirq.c: open_softirq(TASKLET_SOFTIRQ, tasklet_action);
kernel/softirq.c: open_softirq(HI_SOFTIRQ, tasklet_hi_action);
kernel/time/timer.c: open_softirq(TIMER_SOFTIRQ, run_timer_softirq);
lib/irq_poll.c: open_softirq(IRQ_POLL_SOFTIRQ, irq_poll_softirq);
net/core/dev.c: open_softirq(NET_TX_SOFTIRQ, net_tx_action);
net/core/dev.c: open_softirq(NET_RX_SOFTIRQ, net_rx_action);
Just 12!
This pattern repeats across the kernel: stuff that maintainers consider lowish-level is not exported and meant for core kernel code only.

Resources