Posts

Showing posts from December, 2018

Internals of module_init and module_exit

Image
We know from our hello world device driver program  , that on insmod, the function passed in the module_init macro is called, and on rmmod, the argument passed in the module_exit is called. Let's see the definition of this macro, it is present in linux/module.h The purpose of defining __inittest function is to check during compile time, the function passed to module_init() macro is compatible with the initcall_t type. initcall_t is defined in linux/init.h: typedef int (*initcall_t)(void); If you declare module_init function which returns void instead of int, the compiler will throw warning: Loading this module generated an oops message. The last line uses the alias attribute of gcc to assign another name to init_module, so that you can have a better name as per your driver (e.g. cdrom_init instead of init_module), instead of each driver having init_module. Same is the case with module_exit, giving whatever name in module_exit as parameter to cleanup_m...

Tutorial of gcc __attribute__ ((alias))

GCC Attribute alias allows you to specify multiple aliases(other names) for a symbol (function/variable). Example of aliasing a function name: Code: Output: myfunc: Adding 3 with 6: Result:9 myfunc: Adding 3 with 5: Result:8 Notes: You can see, calling add, the compiler will only call myfunc. Also point to be noted is __func__ returns myfunc on call to add. Example of aliasing a variable: Code: Output: Value of new name is :5

Linux Device Driver displaying what character pressed

Image
Theory: When a key is pressed, the keyboard sends a start bit(low)  8 data bits for the scancode odd parity stop bit(high) Keyboard controller reads the data and performs error checking (parity) and if any error asks for retransmission What is scan code? A scan code is a number sent by the keyboard controller once a key has been pressed or released. E.g. "Enter" has a scan code of 0x1C. A keyboard generates two scan codes for each key typed on the system, one scan code for press and the other for release. Release scan code is 128 (80h) plus the press scan code Code: Output: Notes: 1. This driver will not work for USB Keyboard, as there scan codes are different, it works only for the integrated keyboard on the Laptop. 2. kbdus array is for US Keyboard layout. 3. When you press a key, interrupt is generated, the interrupt handler reads the keyboard data register which exists at 0x60, which is the scan code, this scan code is conv...

Linux Device Driver for counting keyboard strokes

Image
For each key pressed on the keyboard, it generates two interrupts (pressed and release). Code: Output: Notes: 1. IRQ line 1 is assigned for keyboard, we register our handler to be called on keyboard interrupt by calling request_irq 2. IRQF_SHARED flag is used for sharing the keyboard interrupt 3. synchronize_irq waits for the specific handler to exit.

Linux USB Device Driver Part6 - Storing Private Data

Image
As there are chances to retrieve information related to interface later in the driver, usb provides an API to store pointer to any data type and saves it in usb_interface structure. static inline void usb_set_intfdata(struct usb_interface *intf, void *data); To retrieve the data back, we will use the following API. static inline void *usb_get_intfdata(struct usb_interface *intf); Let's update over previous driver code, storing a new variable int count in our private data, which represents the number of times the device has been opened Code: Output: Notes: 1. In the probe function, we allocated memory for private data structure, and initialize the members, and call usb_set_intfdata to save the pointer into usb_interface data structure 2. In the open function, we first get the interface structure by using usb_find_interface API and then get the private data structure using usb_get_intfdata API 3. Finally in the disconnect function, we free the memory and set...

What happens internally in Linux Kernel when Process and Thread is created.

Image
In our post , we have came to known that Linux implements threads as standard processes. Let's see in this post, how they are implemented internally. In C, we use fork() to create new process and pthread_create to create a new thread. Both internally uses clone system call provided by Linux Kernel. Process Creation example: #include <stdio.h> int main() { fork(); return 0; } To find the system call :strace ./fork clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fec70651a10) = 4269 Thread Creation Example: #include <stdio.h> #include <pthread.h> void *func(void *arg) { return NULL; } int main(int argc, char *argv[]) { pthread_t thread; pthread_create(&thread,NULL, func, NULL); return 0; } To find the system call: strace ./thread clone(child_stack=0x7f74bf7a2fb0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|C...

CLONE_SIGHAND example

Image
This post we will write a code, which will give us an observation what changes when CLONE_SIGHAND is added and when it is removed. Code: Output: Notes: You can see from the code, when CLONE_SIGHAND was set, parent modifying the default behavior of SIGTERM affected the parent process, and it did not ignore the SIGTERM signal and instead called the signal handler.

CLONE_FILES example

Image
This post we will write a code, which will give us an observation what changes when CLONE_FILES is added and when it is removed. Code: Output: Notes: 1. You can see from the code when we passed CLONE_FILES, when the child close file descriptor, it was closed in the parent process file descriptor too. 2. So, any operations which are performed on file descriptor (read, write, fcntl) by one process will affect the other process too

Kernel thread to print the running tasks on the CPU every 500ms

Image
What is  Kernel Thread? A Kernel Thread is a Linux Task running only in kernel mode. It is not created by running fork() or clone() system calls. What is the use of Kernel Thread? Kernel Threads helps the kernel to perform operations in background. What are the some examples of Kernel Thread? 1. ksoftirqd is Per CPU kernel thread runs processing softirqd. 2. kworker is a kernel thread which processes work queues. What are the differences between Kernel Thread and User Thread? Both Kernel Thread and User Thread are represented by task_struct. The main difference is that there is no address space in kernel threads. mm variable of task_struct is set to NULL. How to Create a Kernel Thread? API For creating a kernel thread. #include <linux/kthread.h> struct task_struct *kthread_create(int (*threadfn)(void *data), void *data, const char name[], ...) Parameters: threadfn -> the function which thread should run data -> Argument for thr...

Linux dmesg command Tutorial

Image
What does dmesg command do? Kernel keeps all the logs in a ring buffer. This is done to avoid the boot logs being getting lost until the syslog daemon starts and collects them and stores them in /var/log/dmesg. We will loss the boot up logs if we don't store them in ring buffer. dmesg command is used to control or print kernel ring buffer. Default is to prints messages from the kernel ring buffer on to console. Important dmesg commands: 1. Clear Ring buffer:  $dmesg -c -> Will clear the ring buffer after printing $dmesg -C -> Will clear the ring buffer but does not prints on the console. 2. Don't Print Timestamps:  $dmesg -t -> Will not print timestamps 3. Restrict dmesg command to list of levels. $ dmesg -l err,warn will print only error and warn messages 4. Print human readable timestamps: $dmesg -T will print timestamps in readable format. Note: Timestamp could be inaccurate. 5. Display the log level in the output: ...

Understanding Makefile of Linux Device Driver

Following is the Makefile we used in our Hello World Device Driver Program . Let's try to understand this file When you run make on the command line, it will execute the following command: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 1. C option to change the directory to /lib/modules/$(shell uname -r)/build 2. make will then read the Makefile present in that location  3. M will specify the location of the source code of the module 4. The kernel Makefile will read our Makefile to find out what to build, we specify that by writing obj-m += hello.o To understand this reading Makefile again, we can simply have a Makefile with the following content: obj-m += hello.o And on the command line run the following command: $ make -C /lib/modules/$(uname -r)/build M=$(pwd) modules It will generate the modules for you.

CLONE_FS Example

Image
This post we will write a code, which will give us an observation what changes when CLONE_FS is added and when it is removed. Code: Output: Notes: 1. You can see when CLONE_FS is set, changing the working directory in the child process has changed in the parent process. 2. Similarly other attributes like root directory will also change if CLONE_FS is set.

CLONE_VM Example

Image
This post we will write a code, which will give us an observation what changes when CLONE_VM is added and when it is removed. Code: Output: Notes: 1. Modifications to Local variable 'buf' by child reflected when CLONE_VM is added 2. Modifications to Global variable 'global_value" by child reflected when CLONE_VM is added 3. Modifications to Heap variable 'heap' by child reflected when CLONE_VM is added.

PID vs TID in Linux

Image
PID Stands for Process ID and TID stands for Thread ID. Each process in Linux Kernel is internally represented by task_struct (present in include/linux/sched.h) To get the process ID, we call getpid() API in Linux and gettid() for thread ID. Let's see what happens internally when we call this API. From the screenshot, we can see that kernel returns pid member of the task_struct structure when we call gettid() and tgid member of the task_struct when we call getpid() tgid -> Thread Group ID. Difference between pid and tgid: Linux implements all threads as standard processes, Each thread will have an unique task_struct and appears to kernel as normal process, and share resources such as address space, open files etc with other processes. The pid field in the task_struct is used to identify the thread of the process , and tgid is used to identify the pid of the thread which started the process When a new process is created, the value of both ...

Hello World Linux Device Driver Program

Image
Let's in this post write a hello world Linux device driver Create a hello.c file with the following content in a new folder Create a Makefile with the following content in the same folder Command to create a module: make Command to load module: insmod hello.ko When you run this command, function specified in module_init will be executed, to check run "dmesg" Command to remove module: rmmod hello When you run this command, function specified in module_exit will be executed, verify it by running "dmesg" Output:

Debugging Linux Kernel Using SystemTap Part-9 - Probing interrupts

Image
In Linux, do_IRQ() function is called on each interrupt, which calls handle_IRQ_event(), which finally calls the handlers registered with request_irq() call. Systemtap already provides scripts/tapset for irq (/usr/local/share/systemtap/tapset/linux/irq.stp) Script: Output: Notes: 1. symname function will print out the raw address 2. kernel_string will get the string at the address passed as argument 3. pn() returns the active probe name

Linux Kernel Driver to print all Processes:name,ID and its State

Image
Linux kernel internally refers processes as tasks.  Kernel stores the list of processes in a circular doubly linked list called the task list . Each task/process is represented in kernel with struct task_struct (defined in <linux/sched.h>). This data structure (task_struct) is huge (1.7 Kilobytes) containing all the information about a specific process.  Let's write a module/device driver which reads the circular linked list and prints the following information for us: Process Name Process ID Process State Before that, we should know what are the different states a process can be: TASK_RUNNING: Process is either currently running or on a run-queue waiting to run TASK_INTERRUPTIBLE: Process is sleeping/blocked. Can be runnable/awaken by a signal TASK_UNINTERRUPTIBLE: Similar to TASK_INTERRUPTIBLE, but does not wakeup on a signal __TASK_TRACED: Process is traced by a debugger e.g. ptrace __TASK_STOPPED: Process execution has stopped. This happens whe...

Linux USB Device Driver Part5 - USB Character driver

Image
In this post, we will try to register our USB Device with the character subsystem (/dev/mydevice) allowing the user space to communicate with the USB Device To register a USB  as character device, we need to call the below API in probe function: int usb_register_dev(struct usb_interface *intf, struct usb_class_driver *class_driver); To unregister, call the below API in disconnect function: void usb_deregister_dev(struct usb_interface *intf, struct usb_class_driver *class_driver); As we know for a device file we need to specify the major number and minor number. The major number is fixed for the character USB devices. It is 180. We need to specify the following in the members of struct usb_class_driver: 1. Name of the device node 2. File operations structure 3. Minor Number Code: O/P:  You can observe from the output, after I loaded the module and connected the device, I got four entries (/dev/mydevice*), this is because the device which I a...

Debugging Linux Kernel using SystemTap Part-8 - Find top 10 system calls executed every 5 seconds

Image
In this post, we will write a system tap script to find out the top 10 system calls being executed in your Linux Machine every 5 seconds. # This script continuously lists the top 10 system calls in the # 5 second interval global syscalls_count probe syscall.* {     syscalls_count[name]++ } function print_sysstop() {     printf("%25s %10s \n", "SYSCALL", "COUNT")     foreach(syscall in syscalls_count- limit 10) {         printf("%25s %10d\n", syscall, syscalls_count[syscall])     }     delete syscalls_count } probe timer.s(5) {     print_sysstop()     printf("---------------------------------------------------------------\n") } Notes: 1. We declared a global array named syscalls_count  2. We have probed for all the system calls using "probe syscall.*", once the system call is probed its count is incremented 3. We are using timer with 5 second interval to print...

Debugging Linux Kernel using KGDB Part 9 - Using Linux Provided GDB Scripts

Image
Linux kernel has provided a collection of helper scripts which can simplify kernel debugging steps. You can observe in the linux source directory a file named vmlinux-gdb.py. To use this, copy the below command in ~/.gdbinit add-auto-load-safe-path /path/to/linux-build List of commands supported by the script can be found by running: (gdb) apropos lx Let's try some of the commands. 1. To find out the kernel command line with which the target booted. "lx-cmdline" 2. To find out the list of processes . "lx-ps" 3. To find out list of loaded modules: lx-lsmod

Linux Commands for Hardware Info - lshw, lspci, lsdev, lscpu, lsblk, lsusb

Image
In this post, we will discuss some of the Linux commands for retrieving hardware information. I am using Ubuntu 14.04 as my development machine. 1. lshw  -> lshw stands for list hardware. It generates detailed information about various hardware devices present on the system by reading the /proc filesystem. Running lshw without any commands will generate full information report about all detected hardware. Note: It should run as root user to get full information Running "lshw -short" will produce brief information For more lshw commands, look at this article:  https://www.binarytides.com/linux-lshw-command/ 2. lspci  -> Displays information about the PCI buses in the system and devices connected to them. Simply run the lspci command to get the PCI information. Running "lspci -vvv" command will generate verbose output, which also contains the name of the driver for that PCI Device. Running "lspci -tree" will di...

What is sudo !!

Image
You can see in the below picture, if you tried to execute a particular command and that needs root permission, you can use sudo !! and it will run the previous command as root without you typing the full command again In the above example, i was trying to create hello.txt file in a directory which requires root permissions, so the touch command failed , then I ran sudo !! which executed the previous command with sudo: sudo touch hello.txt

Debugging Linux Kernel using KGDB Part8 - Debugging Kernel Module

Image
In this post, we will debug the e1000 module present on our Ubuntu VM. Steps for debugging using KGDB: On the target: gdb client needs to know the load address of the kernel module $ cat /sys/module/e1000/sections/.text 0xffffffffc0091000 Switch to KGDB Debugger mode by activating magic sysrq $ echo 'ttyS1,115200' > /sys/module/kgdboc/parameters/kgdboc $ echo g > /proc/sysrq-trigger On the Development Machine: Run the following commands: $ gdb ./vmlinux $ target remote /dev/ttyS1 $ add-symbol-file drivers/net/ethernet/intel/e1000/e1000.ko  0xffffffffc0091000 Let's put breakpoint at e1000_xmit_frame which is called while transmitting a frame. (gdb) break e1000_xmit_frame Breakpoint 1 at 0xffffffffc0092f90: file drivers/net/ethernet/intel/e1000/e1000_main.c, line 3102. (gdb) c Now see as soon as it transmits a packet, system will stop and enter into kgdb session

Debugging Linux Kernel using SystemTap Part-7 - Timer

Image
Systemtap provides an easy way to run your code after a specified time period by providing timers. timer.ms(N) - Probe every N milliseconds timer.s(N) - Probe every N seconds timer.us(N) - Probe every N microseconds timer.ns(N) - Probe every N nanoseconds timer.hz(N) - N probes per second Let's write a handler which fires every two seconds. probe timer.s(2) {     printf("Time:%s\n", ctime(gettimeofday_s())) } O/P: gettimeofday_s() returns the number of seconds since epoch time and ctime() converts this epoch time date You can see the printf statement is executing for every two seconds There is another API provided by systemtap: timer.profile , it's a timer that fires periodically on every CPU. Handlers for this probe are called on each CPU for every timer interrupt.  probe timer.profile {     printf("Time:%s\t CPU:%d\texecname:%s\n", ctime(gettimeofday_s()), cpu(), execname()) } cpu() will print the CPU number on wh...

Debugging Linux Kernel using SystemTap Part6 - Writing Probes for SystemCall

Image
Syntax for writing probes for System Call: probe syscall.<nameofsystemcall> { } E.g. of open systemcall: probe syscall.open {     printf("%s(%d) open (%s)\n", execname(), pid(), argstr) } execname() - prints the name of current process pid() - prints the process id of the current process argstr - pretty-printed form of the entire argument list, without parenthesis O/P:

Linux USB Device Driver Part2- Endpoints Differences - Control, Isochronous, Bulk, Interrupt

Control Endpoints: Used for transferring command and status information. E.g. Resetting the device, Querying information about the device etc. Enumeration of a USB Device is performed by a control Endpoint. Each USB Device has a control endpoint zero, which is bidirectional Bursty, random packets are initiated by the host and uses best effort delivery. 8 bytes packet length in low-speed devices, 8,16,32 or 64-bytes packet length in high speed devices and 64-bytes packet length in full speed devices. Interrupt Endpoints:  Used for small and fast data transfer E.g. Data transfer for serial port, HID Devices like keyboard, mouse etc Can be used for low, high-speed and full speed devices Unidirectional and periodic Maximum packet size: 64 bytes or less for full speed devices 1024 bytes or less for high speed device Bulk Endpoints - Used for large but slower data transfer E.g. Data Transfers of Mass Storage Devices, printers and scanners Bulk pipe is un...

Linux USB Device Driver Tutorial Part-1 - Basics

Image
The USB System architecture consists of three main components: USB Host One or more USB Devices A physical bus represented by USB cable that connects devices with the host computer USB Host is in charge of asking each and every USB device, if it has any data to send. A USB device can never start sending data without first being asked to by the host controller. Which devices needs a Linux USB Driver and which do not? USB Protocol specification define a set of standards that any device of a specific type can follow. If a device follows that standard, then a special driver for that device is not necessary. These different types are called classes (e.g. storage devices, keyboards, mice, joysticks, network devices and modems). Other type of devices that do not fit into these classes require a special vendor-specific driver to be written for that specific device. USB Gadget Driver vs USB Host Driver: USB Host: Driver running on the host (desktop for example) controlling the ...