Driver
Driver
Driver
specific details
▶ Endianness
▶ cpu_to_be32()
▶ cpu_to_le32()
▶ be32_to_cpu()
▶ le32_to_cpu()
▶ I/O memory access
Advantages
▶ No need for kernel coding skills. Easier to reuse code between devices.
▶ Drivers can be written in any language, even Perl!
▶ Drivers can be kept proprietary.
▶ Driver code can be killed and debugged. Cannot crash the kernel.
▶ Can be swapped out (kernel code cannot be).
▶ Can use floating-point computation.
▶ Less in-kernel complexity.
▶ Potentially higher performance, especially for memory-mapped devices, thanks to the
avoidance of system calls.
Drawbacks
▶ Less straightforward to handle interrupts.
▶ Increased interrupt latency vs. kernel code.
kernel Options
1. Tristate
2. Int , hex strings values also
make oldconfig
▶ Needed very often!
▶ Useful to upgrade a .config file from an earlier kernel release
▶ Asks for values for new parameters.
▶ ... unlike make menuconfig and make xconfig which silently set default values
for new parameters.
If you edit a .config file by hand, it’s useful to run make oldconfig afterwards, to set
values to new parameters that could have appeared because of dependency changes.
Prepapration
2. cd /usr/src/linux-headers-3.5.0-17
sudo make modules_prepare
This will
make sure the kernel contains the information required. The target
exists solely as a simple way to prepare a kernel source tree for
building external modules
3. STEPS
1.make oldconfig ,
2. menuconfig
3. make modules_install -> installing modules
4. make install ->install kernel and edit grub file
Only uboot required zimage - > uimage conversion.Uboot can also load DTB
that you can write to the kernel log from user space too:
echo "<n>Debug info" > /dev/kmsg
/proc/kmsg is readonly
Modprobe –r <module> removes the modules and dependent module if not in use
kernel command line, when the driver is built statically into the
kernel:
usb-storage.delay_use=0
using sysfs
/sys/module/name/parameters
How to find/edit the current values for the parameters of a loaded module?
▶ Check /sys/module/<name>/parameters.
▶ There is one file per parameter, containing the parameter value.
▶ Also possible to change parameter values if these files have write permissions
(depends on the module code).
▶ Example:
echo 0 > /sys/module/usb_storage/parameters/delay_use
__init or __exit – not compulsory just when hotplug and freeing of space
Module_init and module_exit necessary.
From a kernel module, only a limited number of kernel functions can be called
▶ Functions and variables have to be explicitly exported by the kernel to be visible
to a kernel module
▶ Two macros are used in the kernel to export functions and variables:
▶ EXPORT_SYMBOL(symbolname), which exports a function or variable to all modules
▶ EXPORT_SYMBOL_GPL(symbolname), which exports a function or variable only to GPL
Modules
Only GPL licensed module can use symbols exported via EXPORT_SYMBOL_GPL ( eg kernel function)
old kernel ( 2.6.32 ) you have to use mknod /dev/.. major minor to create now
now sys api are used , send udev event to create entry in dev
Waitqueue
WaitQueue
Whenever a process must wait for an event (such as the arrival of data or the termination of a process),
it should go to sleep. Sleeping causes the process to suspend execution, freeing the processor for
other uses. After some time, the process will be woken up and will continue with its job when the event
which we are waiting will be occurred.
Wait queue is a mechanism provided in kernel to implement the wait. As the name itself suggests, wait
queue is the list of processes waiting for an event
Kernel module is only compiled – make –C … not linked.
Character and block devices are accessed through inode info via names in filesystem.
Inode contains reference to cdev structure.
There are many ways to Communicate between the User space and Kernel Space, they are:
IOCTL
Procfs
Sysfs
Configfs
Debugfs
Sysctl
UDP Sockets
Netlink Sockets
Some real time applications of ioctl is Ejecting the media from a “cd” drive, to change the Baud Rate of Serial
port, Adjust the Volume,network link up dow.
Fops = unlocked_ioctl
Lockfree Design
1.RCU - > lockfree design – RCU kernel API , use atom
2.Use of Atomic Operation
3. Per cpu variables
Usages of locks
Use mutexes in code that is allowed to sleep
▶ Use spinlocks in code that is not allowed to sleep
(interrupts) or for which sleeping would be too
costly (critical sections)
▶ Use atomic operations to protect integers or
Addresses
Debuggging.
===========
/proc/sys/kernel/printk - > loglevels , some may on console . but all on the kernel log buffer( dmesg)
1.2Pr_info-> modukles
dev_info-> for kerner drivers
2.
#define DEBUG
pr_debug and dev_dbg
3.
Copyright 2009 Jonathan Corbet <corbet@lwn.net>
MMAP
Perf on Custom KernelPert Tool highly Tight to kernel ,
you should/must not any mismatch kernel version perf.
cd /tools/perf
make
cp perf /usr/bin/.
chmod 755 /usr/bin/perf
Interrupt Handler Flags
The third parameter, flags, can be either zero or a bit mask of one or more of the flags
defined in <linux/interrupt.h>.Among these flags, the most important are
nIRQF_DISABLED—When set, this flag instructs the kernel to disable all interrupts
when executing this interrupt handler.When unset, interrupt handlers run with all
interrupts except their own enabled. Most interrupt handlers do not set this flag, as
disabling all interrupts is bad form. Its use is reserved for performance-sensitive interrupts
that execute quickly.This flag is the current manifestation of the SA_INTERRUPT
flag, which in the past distinguished between “fast” and “slow” interrupts.
Irqf_shared
The fifth parameter, dev, is used for shared interrupt lines.When an interrupt handler
is freed (discussed later), dev provides a unique cookie to enable the removal of only the
desired interrupt handler from the interrupt line.Without this parameter, it would be
impossible for the kernel to know which handler to remove on a given interrupt line.You
can pass NULL here if the line is not shared, but you must pass a unique cookie if your
interrupt line is shared.
stack in interrupt
local irq_save and local irq_restore. ( disable and save and enable and restore)
better than above function.
Disaling a particular IRQ on all CPU
void disable_irq(unsigned int irq);
void disable_irq_nosync(unsigned int irq);
void enable_irq(unsigned int irq);
void synchronize_irq(unsigned int irq);
SoftIRQ
Softirqs are a set of statically defined bottom halves that
can run simultaneously on any processor; even two of the same type can run concurrently.
networking. Using softirqs requires more care, however, because two of the same
softirq can run at the same time. In addition, softirqs must be registered statically at compile
time.
If you need to use locks in softirq then prefer to use tasklet, if without lock and per cpu variable can be used
Then use softirq ( if it is crticial and performance is required). There is no point in using locks and using softirq
As whole point of parallel running in all core/cpu is gone.
Tasklets are essentially softirqs in which multiple instances of the same handler cannot run concurrently on multiple
processors.
Tasklet
Two different tasklets can run concurrently on
different processors, but two of the same type of tasklet cannot run simultaneously. code can dynamically register tasklets
we can say tasklet softirq with only single instanace running at a time so no need of lock.
Worqueue
1. Process context
As with softirqs, tasklets cannot sleep.This means you cannot use semaphores or other
blocking functions in a tasklet.Tasklets also run with all interrupts enabled, so you must
take precautions (for example, disable interrupts and obtain a lock) if your tasklet shares
data with an interrupt handler.
Semaphore and mutex cannot be used in softirq or tasklet as they sleep only variant of spinlock can be used.
Workqueue we can use semaphore or mutex as it can sleep.kthread also.
Ksoftirqd
1. Tasklet and softirq is run by per processor kernel thread.
Workqueue
work queues are schedulable and can therefore sleep
kworker kthhead.
why not use kthread over workqueue – just because too many thead in kernel is not recommmeded
instead they are put in quque and thread ( kworker ) process it one by one.
2.tasklet
Tasklets make more sense if the code is not finely threaded.They have a simpler interface
and, because two tasklets of the same type might not run concurrently, they are easier
to implement.Tasklets are effectively softirqs that do not run concurrently.
3.workqueue
Work queues involve the highest overhead
because they involve kernel threads and, therefore, context switching.This is not to
say that they are inefficient, but in light of thousands of interrupts hitting per second (as
the networking subsystem might experience), other methods make more sense. For most
situations, however, work queues are sufficient.
Spin locks can be used in interrupt handlers, whereas semaphores cannot be used because
they sleep. If a lock is used in an interrupt handler, you must also disable local interrupts
(interrupt requests on the current processor) before obtaining the lock. Otherwise, it
is possible for an interrupt handler to interrupt kernel code while the lock is held and attempt
to reacquire the lock
Note
that you need to disable interrupts only on the current processor.
spin_lock_irqsave(&mr_lock, flags);
/* critical region ... */
spin_unlock_irqrestore(&mr_lock, flags);
The routine spin_lock_irqsave()saves the current state of interrupts, disables them
locally, and then obtains the given lock. Conversely, spin_unlock_irqrestore()unlocks
the given lock and returns interrupts to their previous state.
Spinlock in uniprossor
On uniprocessor systems, the previous example must still disable interrupts to prevent
an interrupt handler from accessing the shared data, but the lock mechanism is compiled
away.The lock and unlock also disable and enable kernel preemption, respectively.
Semaphores
Semaphores in Linux are sleeping locks.When a task attempts to acquire a semaphore
that is unavailable, the semaphore places the task onto a wait queue and puts the task to
sleep.The processor is then free to execute other code.When the semaphore becomes
available, one of the tasks on the wait queue is awakened so that it can then acquire the
semaphore.
Sequence Lock
A prominent user of the seq lock is jiffies, the variable that stores a Linux machine’s
Uptime
On machines that cannot atomically
read the full 64-bit jiffies_64 variable, get_jiffies_64() is implemented using
seq locks:
u64 get_jiffies_64(void)
{
unsigned long seq;
u64 ret;
do {
seq = read_seqbegin(&xtime_lock);
ret = jiffies_64;
} while (read_seqretry(&xtime_lock, seq));
return ret;
}
Updating jiffies during the timer interrupt, in turns, grabs the write variant of the
seq lock:
write_seqlock(&xtime_lock);
jiffies_64 += 1;
write_sequnlock(&xtime_lock);
Kernel Preemption
.The most frequent of these situations is per-processor data. If the
data is unique to each processor, there might be no need to protect it with a lock because
only that one processor can access the data . But we need kernel preemption to be disabled.
So that only one process running in one cpu can modify it.
Per cpu variable can be run in other core.pre-empt_disable and prempt emable
.
Elegant API is
Get_cpu and put_cpu.
Get_cpu also disables kernel preemption.
We can use get_cpu() and put_cpu() to replace
preempt_disable()
cpu = smp_processor_id() and
preempt_enable()
for slightly better code.
Sequence lock is used in calculating the 64jiffies, using sequence_lock there is special lock xtime_lock
To access 64bit jffies.
int x = 1;
if (*(char *)&x == 1)
/* little endian */
else
/* big endian */
Slab Layer
Allocating and freeing data structures is one of the most common operations inside any
kernel.To facilitate frequent allocations and deallocations of data, programmers often
introduce free lists.A free list contains a block of available, already allocated, data structures.
When code requires a new instance of a data structure, it can grab one of the structures
off the free list rather than allocate the sufficient amount of memory and set it up for the
data structure. Later, when the data structure is no longer needed, it is returned to the free
list instead of deallocated. In this sense, the free list acts as an object cache, caching a frequently
used type of object
ECN vs PFC
you can easily find Pause frame from wireshark with the filter "macc.opcode == pause" as shown below.
Trigger interrupt
static ssize_t etx_read(struct file *filp, char __user *buf, size_t len, loff_t *off)
{
printk(KERN_INFO "Read Function\n");
asm("int $0x3B"); //Triggering Interrupt. Corresponding to irq 11
return 0;
}
KernelModule: send_sig_info(SIGRTMIN)
UserProcess: sigaction(SIGRTMIN) (Wait signal by sa_sigaction handler)
Container_of()
I know the address of one member in the structure. But i don’t know the address of that structure. That
structure may have many members. So we can find the address of the structure using
this container_of macro in Linux Kernel.
7 #include <stdio.h>
8
9 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
10
11 #define container_of(ptr, type, member) ({ \
12 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
13 (type *)( (char *)__mptr - offsetof(type,member) );})
14
15 int main(void)
16 {
17 struct sample {
18 int mem1;
19 char mem2;
20 };
21
22 struct sample sample1;
23
24 printf("Address of Structure sample1 (Normal Method) = %p\n", &sample1);
return 0;
}
Proc vs Sysfs
From the Linux 2.5 development cycle, a new interface called the /sys file system has been introduced. Sysfs is a
RAM based file system.
It is designed to export the kernel data structures and their attributes from the kernel to the user space, which then
avoids cluttering the /proc file system.
The advantages of sysfs over procfs are as follows:
- A cleaner, well-documented programming interface
- Automatic clean-up of directories and files, when the device is removed from the system
- The enforced one item per file rule, which makes for a cleaner user interface
O(1) was good for server loads not got interactive process.
Latest scheduled is CFS
Scheduler Classes
The Linux scheduler is modular, enabling different algorithms to schedule different types
of processes.This modularity is called scheduler classes. Scheduler classes enable different,
pluggable algorithms to coexist, scheduling their own types of processes
This flag is set (by the networking code) to activate promiscuous operation. By default,
Ethernet interfaces use a hardware filter to ensure that they receive broadcast packets and
packets directed to that interface's hardware address only. Packet sniffers such as tcpdump set
promiscuous mode on the interface in order to retrieve all packets that travel on the interface's
transmission medium