Using hrtimers in the Linux Kernel - linux

After searching online and on Stackoverflow for a great deal of time, I have come to realize there are not a lot of concrete examples of using hrtimers in the Linux Kernel. Any example I have found is vague and does not explain the functionality of their program or does not explain how the hrtimers are working well enough for me to understand.
I know there is documentation at /include/linux/hrtimer.h, but that documentation is not clear and seems to assume I am already familiar with them.
Can anyone give a basic example of using this timer?

Simple example, callback every 100ms:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/hrtimer.h>
#include <linux/ktime.h>
static struct hrtimer test_hrtimer;
static u64 sampling_period_ms = 100; // 100ms
static u32 loop = 0;
static enum hrtimer_restart test_hrtimer_handler(struct hrtimer *timer)
{
pr_info("test_hrtimer_handler: %u\n", ++loop);
hrtimer_forward_now(&test_hrtimer, ms_to_ktime(sampling_period_ms));
return HRTIMER_RESTART;
}
static int __init test_hrtimer_init(void)
{
hrtimer_init(&test_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
test_hrtimer.function = &test_hrtimer_handler;
hrtimer_start(&test_hrtimer, ms_to_ktime(sampling_period_ms), HRTIMER_MODE_REL);
pr_info("init test_hrtimer.\n");
return 0;
}
static void __exit test_hrtimer_exit(void)
{
hrtimer_cancel(&test_hrtimer );
pr_info("exit test_hrtimer.\n");
return;
}
module_init(test_hrtimer_init);
module_exit(test_hrtimer_exit);
MODULE_LICENSE("GPL");

Related

Get function from x64 instruction pointers?

This is an exercise that I want to implement in real code
I send a signal to my app (x86-64 linux). My app then executes code that walks the stack and prints out instruction pointers. I'm not sure if I want only the last few or everything to main. Anyway, I'm releasing an optimized binary without debug information. I strip symbols before its distributed.
I was wondering, how do I translate it back? I don't need to translate it in the app. I can use the machine I build to go from rip's to functions. I was thinking maybe I should also distribute one with debug information and maybe have the user be able to see the function+line but I think line will be unlikely if its optimized well
Another problem I have is my code doesn't seem to walk past the signal function. backtrace figures it out but I'm trying to do this without libc. Here's some code
#include <signal.h>
#include <cstdio>
typedef unsigned long long u64;
int mybacktrace();
#include <execinfo.h>
#include <unistd.h>
void print_stacktrace(void) {
size_t size;
enum Constexpr { MAX_SIZE = 1024 };
void *array[MAX_SIZE];
size = backtrace(array, MAX_SIZE);
backtrace_symbols_fd(array, size, STDOUT_FILENO);
}
void mysig(int signo) {
mybacktrace();
_exit(1);
}
int mybacktrace() {
u64*p;
p = (u64*)((u64)&p + 16); //seems to work correctly
for (int i = 0; i < 10 && (u64)p >= 1<<16; i++)
{
printf("%d %p\n", i, p[1]);
p = (u64*)(p[0]);
}
print_stacktrace(); return 0;
return 0;
}
int test()
{
return mybacktrace();
}
int main(int argc, char *argv[])
{
signal(SIGILL, mysig);
test();
__builtin_trap();
return 0;
}

Problem with hotplugging device driver module

I'm writing a module that when you plug in a usb mouse prints "hello world". The problem comes when I plug in the mouse, dmesg prints six times the below message:
[ 7367.238560] helwor_mod: disagrees about version of symbol
module_layout
This is my code
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/usb.h>
#include <linux/usb/input.h>
#include <linux/hid.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Isaac Lleida <isakyllr#opmbx.org>");
MODULE_VERSION("0.1");
static struct usb_device_id usb_mouse_id_table [] = {
{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
USB_INTERFACE_PROTOCOL_MOUSE) },
{ }
};
MODULE_DEVICE_TABLE(usb, usb_mouse_id_table);
static int mouse_probe(struct usb_interface *iface,
const struct usb_device_id *id)
{
pr_info("Hello World!");
return 0;
}
static void mouse_disconnect(struct usb_interface *iface)
{
pr_info("Bye World!");
}
static struct usb_driver mouse_driver = {
.name = "usbmouse",
.probe = mouse_probe,
.disconnect = mouse_disconnect,
.id_table = usb_mouse_id_table,
};
module_usb_driver(mouse_driver);
static int __init hello_init(void)
{
int res = 0;
res = usb_register(&mouse_driver);
if(res)
pr_err("usb_register failed with error %d", res);
return res;
}
static void __exit hello_exit(void)
{
pr_debug("USB Mouse Removed...");
usb_deregister(&mouse_driver);
}
I have been googling all the afternoon and still don't know how to solve it.
I hope someone can help me, thanks.
This is related:
module_layout version incompatibility
I'd bet that the kernel sources (headers) you're using to compile your module are from a different kernel version than then one you're running.
Problem solved. This issue is produced because the device is being controled by another driver and it's loaded in the system. Just unload it and load your driver module.
And sorry Gilles for the offtopic.

linux ptrace() get function information

i want to catch information from user defined function using ptrace() calls.
but function address is not stable(because ASLR).
how can i get another program's function information like gdb programmatically?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <dlfcn.h>
#include <errno.h>
void error(char *msg)
{
perror(msg);
exit(-1);
}
int main(int argc, char **argv)
{
long ret = 0;
void *handle;
pid_t pid = 0;
struct user_regs_struct regs;
int *hackme_addr = 0;
pid = atoi(argv[1]);
ret = ptrace(PTRACE_ATTACH, pid, NULL, NULL);
if(ret<0)
{
error("ptrace() error");
}
ret = waitpid(pid, NULL, WUNTRACED);
if(ret<0)
{
error("waitpid ()");
}
ret = ptrace(PTRACE_GETREGS, pid, NULL, &regs);
if(ret<0)
{
error("GETREGS error");
}
printf("EIP : 0x%x\n", (int)regs.eip);
ptrace(PTRACE_DETACH, pid, NULL, NULL);
return 0;
}
ptrace is a bit ugly, but it can be useful.
Here's a ptrace example program; it's used to make I/O-related system calls pause.
http://stromberg.dnsalias.org/~strombrg/slowdown/
You could of course also study gdb, but ISTR it's pretty huge.
You might also check out strace and ltrace, perhaps especially ltrace since it lists symbols.
HTH
You probably want to call a function that resides in a specific executable (probably, a shared object). So, first, you will have to find the base address this executable is mapped on using
/proc/pid/maps
After that, you need to find the local offset of the function you are interested in, and you can do this in two ways:
Understand the ELF file format (Linux native executable format), and searching the desired function using the mapped file (This requires some specialty)
Using a ready to use elfparser (probably readelf tool) to get the function offset under the executable. Note that you will have to figure out the real local offset since this tool usually gives you the address as if the executable was mapped to a specific address

Kernel Module to Ethernet Packet Echo

I develop a linux kernel module to re-transmit some ethernet packet (do the echo). THe packet arrives, i check the ethernet destination address, and if it is for me, i re-transmit. If not i do nothing.
I used dev_pack_eth to define my protocol handler to recieve all ethernet packet (EHT_P_ALL) and dev_queue_xmit to transmit the skb buff received.
It works, the echo is functional but...
Sometimes, very often. the kernel crashs and i don't know why.
When i re-transmit the packet, i return NET_RX_Sucess.
When i don't re-transmit i use kfree_skb to free the skb buff received and return NET_RX_DROP.
I think the problem my be on this issues. Can you help me?
If needed i could post the kernel module code.
Best Regards!
------------Edit:Code added--------
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
#include <linux/skbuff.h>
#include <linux/if_ether.h>
#include <linux/netdevice.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_bridge.h>
#include <asm-generic/types.h>
/*Buscar as interfaces de rede*/
struct net_device *dev_eth0;
struct net_device *dev_eth1;
int contador;
static struct packet_type hook; /* Initialisation routine */
void handler_add_config (void);
void handler_remove(void);
void print_mac_hdr(struct ethhdr *eth);
static int hook_func( struct sk_buff *skb)
{
struct ethhdr *eth;
struct ethhdr aux;
eth= eth_hdr(skb)
print_mac_hdr(eth);
/*If destination isn't the same that dev_addr, the packet is not for me: do nothing*/
if(memcmp(eth->h_dest,skb->dev->dev_addr,ETH_ALEN)!=0)
{
printk("Não são iguais!!!\n");
}
else
{
/*Swap addr*/
memcpy(&(aux.h_dest),eth->h_dest,ETH_ALEN);
memcpy(eth->h_dest,eth->h_source,ETH_ALEN);
memcpy(eth->h_source,&(aux.h_dest),ETH_ALEN);
/*Re build ther hearders*/
skb->data = (unsigned char *)skb->mac_header;
skb->len += ETH_HLEN;
skb->pkt_type = PACKET_OUTGOING;
/*Send*/
if(dev_queue_xmit(skb)!= NET_XMIT_SUCCESS)
{
printk("Erro na transmissão\n");
}
else
{
printk("Trama retransmitida com sucesso\n");
return NET_RX_SUCCESS;
}
}
kfree_skb(skb);
return NET_RX_DROP;
}
/*Print eth headers*/
void print_mac_hdr(struct ethhdr *eth)
{
printk("Destino: %02x:%02x:%02x:%02x:%02x:%02x \n",eth->h_dest[0],eth->h_dest[1],eth->h_dest[2],eth->h_dest[3],eth->h_dest[4],eth->h_dest[5]);
printk("Origem: %02x:%02x:%02x:%02x:%02x:%02x\n",eth->h_source[0],eth->h_source[1],eth->h_source[2],eth->h_source[3],eth->h_source[4],eth->h_source[5]);
printk("Proto: 0x%04x\n",ntohs(eth->h_proto));
}
/*Configure Protocol Handler*/
void handler_add_config (void)
{
hook.type = htons(ETH_P_ALL);
hook.func = (void *)hook_func;
hook.dev = NULL;
dev_add_pack(&hook);
printk("Handler Protocol adicionado!!!!\n");
}
/*Unregist protocol handler*/
void handler_remove(void)
{
dev_remove_pack(&hook);
printk("Handler Protocol removido!!!!\n");
synchronize_net();/*Sincronizar a rede!*/
}
/*Init module and protocol handler*/
static int __init hook_init(void)
{
printk("Hello:I'm the hook module!!!!\n");
contador =0;
dev_eth0=dev_get_by_name(&init_net,"eth0");
dev_eth1=dev_get_by_name(&init_net,"eth1");
handler_add_config();
return 0;
}
/*Remove module and protocol handler*/
static void __exit hook_exit(void)
{
printk("Hook module says Goodbye!!!!!\n");
handler_remove();
}
module_init(hook_init);
module_exit(hook_exit);
MODULE_LICENSE("GPL");
i think when u are returning return NET_RX_DROP; it causes problem because there are basically return types in hooks are ...
Return Code Meaning
NF_DROP Discard the packet.
NF_ACCEPT Keep the packet.
NF_STOLEN Forget about the packet.
NF_QUEUE Queue packet for userspace.
NF_REPEAT Call this hook function again.
& u are returning NET_RX_DROP so try to use NF_DROP.
Look at af_x25.c in net/x25 for a sample implementation of the same where they return 0 even on a drop. BTW didn't understand why are you incrementing skb->len when all you are doing is swapping the mac addresses ? I.e why the need to rebuild hdrs in that sense? Am i missing something here?
You are probably crashing because you are freeing the slngle copy of sk_buff by calling kfree_skb(skb);

Try...catch causes segmentation fault on embedded ARM with posix threads

Today, I posted a problem about a segmentation fault after destruction of a std::string (see this post). I've stripped the code so that I don't use the STL and still have a segmentation fault sometimes.
The following code works just fine on my PC running Linux. But using the ARM crosscompiler suppplied by the manufactor of our embedded device, it gives a segmentation fault just before catch (...).
This problems seems to have a link with this post in Google Groups, but I haven't found any solution yet.
The code is compiled using an ARM cross compiler
Any suggestions are still welcome!
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void *ExecuteThreadMethod(void *AThread);
class Thread
{
private:
pthread_t internalThread;
public:
void RunSigSegv()
{
try
{
for (int i = 0; i < 200; i++)
{
usleep(10000);
}
} // <---- Segmentation fault occurs here
catch(...)
{
}
}
void Start()
{
pthread_attr_t _attr;
pthread_attr_init(&_attr);
pthread_attr_setdetachstate(&_attr, PTHREAD_CREATE_DETACHED);
pthread_create (&internalThread, &_attr, ExecuteThreadMethod, this);
}
};
void *ExecuteThreadMethod(void *AThread)
{
((Thread *)AThread)->RunSigSegv();
pthread_exit(NULL);
}
Thread _thread1;
Thread _thread2;
Thread _thread3;
Thread _thread4;
void s()
{
_thread1.Start();
_thread2.Start();
_thread3.Start();
_thread4.Start();
}
int main(void)
{
s();
usleep(5000000);
}
I once encountered a problem like this which was caused by linking with a version of libstdc++ with no threading support, meaning that all threads shared a common exception handling stack with disastrous consequences.
Make sure the cross-compiler and its libraries were configured with --enable-threads=posix.
Just a diagnostic question: What happens if you don't detach the thread in Start()? You'd have to pthread_join() the threads back in main().
Also, have you considered Boost's threads? That might be more appropriate since you're using C++ rather than C.

Resources