I have a simple module, written as follows:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
MODULE_LICENSE("GPL");
static int __init hellomod_init(void)
{
printk(KERN_DEBUG, "Hello, world!\n");
return 0;
}
static void __exit hellomod_exit(void)
{
printk(KERN_DEBUG, "Goodbye, world!");
}
module_init(hellomod_init);
module_exit(hellomod_exit);
and
$ cat /proc/sys/kernel/printk
7 7 7 7
so that any level messages should output.
The module loads and this can be verified with lsmod, however no output is produced when loading or unloading the module and checking dmesg.
I have tried replacing KERN_DEBUG with lower levels and still no output, so I don't think the log level is the issue.
How else can I verify the hellomod_init() function is called? If it is not being called, what is my error?
I am running and compiling against kernel version 4.6.1-2 on Arch Linux.
There shouldn't be a comma after KERN_DEBUG. So it should look something like this:
static int __init hellomod_init(void)
{
printk(KERN_DEBUG "Hello, world!\n");
return 0;
}
Related
local_irq_disable()is used to disable all interrupts on the current processor
i wrote a basic code to test local_irq_disable().
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/irqflags.h>
static int __init my_init(void)
{
pr_info("module is loaded on processor:%d\n", smp_processor_id());
local_irq_disable();
ssleep(10);
local_irq_enable();
return 0;
}
static void __exit my_exit(void)
{
}
MODULE_LICENSE("GPL");
module_init(my_init);
module_exit(my_exit);
When i load this on my system, it prints the following message:
[10478.930188] module is loaded on processor:5
And when i run "watch -d -n 0.2 'cat /proc/interrupts'", it still shows interrupts on those processor, what i am missing here?
I would like to write some code (for example as a small kernel module) to instrument local interrupts on Linux running on the x86-64 architecture, i.e. I would like to write some kind of handler that is called by the kernel every time a local interrupt is triggered by the APIC.
The handler would then check whether a certain process is currently running and inspect said process' memory.
I realize that what I am trying to do may not be good engineering practice, but my aim is to create a hacky one-off solution for exploration/research purposes.
In the ideal case, there would be some kind of function similar to request_irq [1] (which as far as I can tell is used for handling interrupts from devices like keyboards, network cards, ...) allowing me to tell the kernel to run my code every time a local timer interrupt occurs.
Does anybody have any pointers on how to accomplish this?
Does the kernel provide an API for registering a handler for local interrupts?
If not, I could directly modify the kernel's source code for handling interrupts. Where in the kernel would I find this code?
Edit: Here is what my research so far has found.
TLDR:request_irq is not the way to hook local timer interrupts.
According to Understanding the Linux Kernel, Table 4.2 [2], the interrupt vector 0xef is allocated to Local APIC timer interrupts. The kernel source confirms this [3].
Since request_irq takes an interrupt vector as its first argument, let's try registering a handler for this vector inside a kernel module:
#include <linux/module.h>
#include <linux/kernel.h> // included for KERN_INFO
#include <linux/init.h> // included for __init and __exit macros
#include <linux/interrupt.h> // included for IRQF_ and request_irq
#include <linux/irqreturn.h> // included for IRQ_NONE
#include <asm/irq_vectors.h> // included for LOCAL_TIMER_VECTOR
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Instrument local timer interrupts");
static int DEVICE_COOKIE = 1;
static int count = 0;
static irqreturn_t handler(int irq, void *dev) {
count++;
return IRQ_NONE;
}
static int __init test_init(void) {
int status;
printk(KERN_INFO "Running request_irq\n");
status = request_irq(
LOCAL_TIMER_VECTOR,
&handler,
IRQF_TIMER,
"foobar",
&DEVICE_COOKIE);
if (status == 0) {
printk(KERN_INFO "Successfully installed handler\n");
return 0;
} else {
printk(
KERN_INFO "Failed to install handler. error code: %d\n",
status);
return -1;
}
}
static void __exit test_cleanup(void) {
free_irq(LOCAL_TIMER_VECTOR, &DEVICE_COOKIE);
printk(KERN_INFO "Goodbye kernel. I saw %d interrupts.\n", count);
}
module_init(test_init);
module_exit(test_cleanup);
When we try to insert the module with insmod, request_irq returns -EINVAL:
[74890.287173] Running request_irq
[74890.287174] Failed to install handler. error code: -22
So where does the -EINVAL come from?
Reading through the kernel source, we find that request_irq is just a wrapper around request_threaded_irq [4]. request_threaded_irq calls irq_to_desc and returns -EINVAL if the call fails. We can easily check whether this is the case with another small kernel module:
#include <linux/kernel.h> // included for KERN_INFO
#include <linux/init.h> // included for __init and __exit macros
#include <linux/interrupt.h> // included for IRQF_ and request_irq
#include <linux/irqreturn.h> // included for IRQ_NONE
#include <asm/irq_vectors.h> // included for LOCAL_TIMER_VECTOR
#include <linux/irqnr.h> // included for irq_to-desc
#include <linux/irqdesc.h> // included for irq_desc
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Call irq_to_desc(LOCAL_TIMER_VECTOR)");
static int __init test_init(void) {
struct irq_desc *desc;
desc = irq_to_desc(LOCAL_TIMER_VECTOR);
if (!desc) {
printk(KERN_INFO "irq_to_desc(LOCAL_TIMER_VECTOR) failed");
return -1;
}
return 0;
}
static void __exit test_cleanup(void) {
}
module_init(test_init);
module_exit(test_cleanup);
And indeed it fails:
[75787.142533] irq_to_desc(LOCAL_TIMER_VECTOR) failed
[1] www.makelinux.net/books/lkd2/ch06lev1sec3
[2] www.safaribooksonline.com/library/view/understanding-the-linux/0596005652/ch04s06.html
[3] lxr.free-electrons.com/source/arch/x86/include/asm/irq_vectors.h?v=4.8#L108
[4] lxr.free-electrons.com/source/kernel/irq/manage.c?v=4.8#L1634
Yesterday I installed a very simple kernel module in my embedded Linux system. "hello.ko".
When I install this module to our system, it's normally:
#insmod hello.ko
Initing kernel module
#
#lsmod
hello 638 0 - Live 0xf628f000
But when I remove this kernel module, It can be removed normally but rmmod notice 'hello.ko' not found
# rmmod hello
Cleaning kernel module
rmmod: module 'hello' not found
#lsmod <------------------- already be removed
#
# uname -a
# Linux SWITCH 2.6.32 #8 Thu Jun 23 20:34:48 KST 2016 ppc GNU/Linux
It's very strange. Could anyone explain for me why 'hello.ko' is removed but there's log 'rmmod module not found'?
The following are source code of hello.ko
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/config.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/string.h>
int init_module(void)
{
printk (KERN_EMERG "Initing kernel module\n");
return 0;
}
void cleanup_module(void)
{
printk (KERN_EMERG "Cleaning kernel module\n");
}
MODULE_DESCRIPTION ("Kernel function replacement module");
MODULE_AUTHOR ("DASAN Networks Inc.");
MODULE_LICENSE ("GPL");
You need to add few things in my opinion __init and __exit macros and module_init and module_exit macros, try with:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/string.h>
static int __init init_example(void)
{
printk (KERN_EMERG "Initing kernel module\n");
return 0;
}
static void __exit cleanup_example(void)
{
printk (KERN_EMERG "Cleaning kernel module\n");
}
module_init(init_example);
module_exit(cleanup_example);
MODULE_DESCRIPTION ("Kernel function replacement module");
MODULE_AUTHOR ("DASAN Networks Inc.");
MODULE_LICENSE ("GPL");
I have a hollowworld.c :
/* hello.c */
#include <linux/kernel.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
int init_module(void)
{
printk("Hello world!\n"); /* printk = kernel printf, to the console */
return 0;
}
void cleanup_module(void)
{
printk("Goodbye world!\n");
return;
}
how create a makefile for program.c and how to compile and execute in Real Time Application Interface ?
To compile a kernel module, refer to other drivers in the kernel source tree. You will find it the Makefile as simple as one line in your example:
obj-M += hollowworld.o
I have added a hello world system call to Linux kernel 3.16, then I compile and ran it. I called my system call by syscall function but it did not print any thing and output of syscall function was not -1.
This is my system call code:
#include <linux/kernel.h>
asmlinkage long sys_hello(void){
printk("hello world\n");
return 0;
}
and this my c program code to call my system call:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include <string.h>
#include <errno.h>
int main(void){
printf("function\n");
if(syscall(317)==-1){
printf("no\n");
}
else{
printf("yes\n");
}
return 0;
}
The output of c program is:
function
yes
How can I find my system call is added to kernel correctly?
printk wouldn't necessarily print to your current tty; to see your message use the dmesg command in your shell. See also this one if it does not show up on dmesg