Tag Archive : kernel

/ kernel

Debugging Linux Kernel on QEMU Using GDB

March 21, 2016 | Article | No Comments

Kernel is magic. Well, not really. All my experiences involving programming in userland. Could I step up to enter the land of kernel? Sure, but before that I need to arm myself with knowledge. Especially when dealing with kernel debugging.

This article will discuss about kernel debugging. When writing this, I use:

  • Linux Kernel 4.5
  • GDB 7.7.1
  • Qemu 2.5.0
  • Busybox 1.24.2
  • ParrotSec Linux for host

Although in the end we can run minimalistic kernel, this approach is not close to “real world” yet.

Preparation

Download the kernel source code from https://www.kernel.org/ and extract it to /usr/src

wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.5.tar.xz
mv linux-4.5.tar.xz /usr/src
cd /usr/src
tar -xf linux-4.5.tar.xz -C linux

Download busybox and extract it to /usr/src. We will use this for creating initramfs.

wget https://busybox.net/downloads/busybox-1.24.2.tar.bz2
mv busybox-1.24.2.tar.bz2
cd /usr/src
tar -xf busybox-1.24.2.tar.bz2 -C busybox

ParrotSec is debian derivative.

I use latest Qemu, you can read it from here.

Compile Linux Kernel

It’s a bit different to usual routine, we need to enable debug info.

cd /usr/src/linux
mkdir build
make menuconfig O=build

Select “Kernel hacking” menu.

Go to “Compile-time checks and compiler options”.

  • Enable the “Compile the kernel with debug info”
  • Enable the “Compile the kernel with frame pointers”
  • Enable the “Provide GDB scripts for kernel debugging”.

Search for “KGDB: kernel debugger” and make sure it is checked.

Go to the build directory and build from there

cd build
make bzImage -j $(grep ^Processor | wc -l)

Creating Initramfs

We need some kind of environment with basic command line tools. Something that provided by binutils, like: ls, cat, mkdir, etc. It is called initramfs (Initial RAM file system). The idea is to provide a minimal “root file system” as a temporary file system so Kernel can prepare all works before mounting the real file system. We will use Busybox.

cd /usr/src/busybox
mkdir build
make menuconfig O=build

Select “Busybox Settings” > “General Configuration” and uncheck the “Enable options for full-blown desktop systems” and check”. Go back and select “Build Options” and check “Build BusyBox as a static binary (no shared libs).

make && make install

This will create a new directory “_install” and install our busybox there. This _install will be base for initramfs.

Next we create a new “initramfs” directory and create some configuration files inside.

mkdir /usr/src/initramfs
cd /usr/src/initramfs
cp -R /usr/src/busybox/build/_install rootfs
cd rootfs
rm linuxrc
mkdir -p dev etc newroot proc src sys tmp

We don’t need “linuxrc” sine we are going to use initramfs boot scheme.

Create a file etc/wall.txt and fill it:

######################################
#                                    #
#      Kernel Debug Environment      #
#                                    #
######################################

Remember init? Once our kernel is up, we need init to spawn everything necessary. However in our minimalistic system, our init only needed to spawn tty. Now create and populate init file with following content.

#!/bin/sh
dmesg -n 1

mount -t devtmpfs none /dev
mount -t proc none /proc
mount -t sysfs none /sys

cat /etc/wall.txt

while true; do
   setsid cttyhack /bin/sh
done

The cttyhack is a small utility for spawning tty device. This way, we can rest assure that when we execute the “exit” command new shell will be started automatically.

We need to make the init file is executable.

chmod +x init

Next we need to pack initramfs.

cd /usr/src/initramfs/rootfs
find . | cpio -H newc -o | gzip > ../rootfs.igz

Running Kernel on Qemu

Next thing to do is to launch the kernel inside Qemu.

qemu-system-x86_64 -no-kvm -s -S \
-kernel /usr/src/linux/build/arch/x86/boot/bzImage \
-hda /mnt/jessie.ext3 -append "root=/dev/sda"

At this point, we will see a blank QEMU terminal windows.

The -s option is a shorthand for -gdb tcp::1234, i.e. open a gdbserver on TCP port 1234.

The -S option stops the CPU to start at startup. Now QEMU is waiting for kernel to start in debug mode.

Running GDB

The QEMU had launched the kernel and waiting for debugging. The next thing is to launch GDB and do the debugging.

gdb

In our host, we need to load the the same kernel load in QEMU and point our target to QEMU.

file /usr/src/linux/build/arch/x86/boot/bzImage
set architecture i386:x86-64:intel
set remote interrupt-sequence Ctrl-C
target remote :1234

Let’s try it, using GDB:

continue
bt

As for now, GDB still not appreciate the size of registers changing. As for our kernel, there is a time when our kernel change from 16 bit to 32 bit (or 64 bit). You might notice that when we run QEMU we specify -S so QEMU will stop at startup. At that time, Linux will change to full 64 bit (or 32 bit) kernel. If you don’t do something, GDB will keep complaining about “remote packet reply is too long”.

To circumvent it, we can just disconnect and then reconnect.

disconnect
set architecture i386:x86-64:intel
target remote :1234

QEMU [Paused]_021  LXTerminal_022

Linux Kernel Packaging

December 9, 2015 | Article | No Comments

If you wish to install linux kernel without doing compilation stage, you can always use prebuilt binary package of kernel image. Just take the package to the target machine and install it. The package you use is built by someone else. So if you know how to build Linux kernel from source, how can you make a package from it?

For creating the build package, while building kernel, instead of giving ‘make’ command alone do one of following command. These commands will creates bzImage and modules and then pack them into a package file. The available commands are:

make rpm-pkg
make binrpm-pkg
make deb-pkg
make tar-pkg
make rargz-pkg
make tarbz2-pkg

Linux Boot Process – Kernel

December 9, 2015 | Article | No Comments

In order for a computer to successfully boot into device we know, a computer should pass some process which we refer as boot process. The BIOS, operating system, and harware components must all be working properly. Failure of any of these three elemens will likely result in a failed boot sequence.

After a boot loader does it jobs (load the kernel) it will terminate itself and the control will be passed to the kernel.

When a Linux kernel is loaded and ran, it is actually running two process for completely load kernel to memory. First one is bootstrapping, and second one is the process in the kernel itself.

In earlier phase kernel will use a bootstrap which is assembly code added to the image. When bzImge is loaded , the code of bootstrap starts executing. The tasks of bootstrap are,

  1. Forcing cpu to go into protected mode. In protected mode we have 4 GB of virtual address space or virtual addressing enabled.
  2. Enabling the MMU (Memory Management Unit) . MMU has got address translation ability , mapping between virtual addresses and physical addresses. CPU contains MMU instruction set.
  3. Decompressing the linux kernel. You can see “Decompressing Linux….” Messages on console at this point.
  4. Calling “start_kernel” function after that. start_kernel is similar to main function. kernel image starts running and initializes all the devices , schedulers, console etc. . You can see lot of text flying on the screen related to this. kernel boots up from here.

When bootstrapping done, the kernel take the process. Kernel does:

  1. Kernel initialize CPU and performs the “Bogo MIPS” calculation. Though BIOS has already intialized CPU but kernel does not depend upon BIOS initialization. It will re-initialize the CPU again. It will create one structure and stores all the CPU details in it. After that it performs “Bogo MIPS”calculation. Using “Bogo MIPS” calculation kernel estimates the cpu speed. At bootup time, you can see the message ” Bogo MIPS is …..” .
  2. Kernel re-initializes parallel ports, serial ports and all the on-board controllers like USB, IDE, SCSI, Serial, parallel, timers, RTC etc. These startup drivers are also called BSP drivers or Board Support Drivers.
  3. Interrupts will be enabled. All the data structures required to hold the interrupts including interrupt descriptor table will be setup , i.e. which device is using which interrupt, IRQ details will be filled.

  4. File system required to read from this disk, /boot , /root , /etc , /home etc. is initialized. File system must be loaded now so that can now start using disk.

  5. After this loader will be started. Loader starts a process that is registered in the PCB with PID ‘0’ . Name of this process is swapper.

  6. “swapper” will start a thread called “init” thread. “init” is a kernel thread. “init” kernel thread will look into /bin and look for a program whose name is “init”. This kernel thread is told for where to look for init process via boot parameter in bootloader configuration file. If kernel thread doesn’t find init there , it becomes a reason for kernel panic and the booting stops there. This may also happen if file system is not initialized . “init” thread looks into /bin and starts executing init process. init’s parent is “init” thread. /bin/init is registered as PID 1 and this is the first user space process.

Kernel has loaded, but the booting process has not stopped yet.

Linux Kernel Configuration

December 9, 2015 | Article | No Comments

Having Linux kernel source code allow us to open possibility to customize / configure the kernel as you wish. Main kernel image is built as a static image, and some part of linux kernel image is also built as loadable modules (device driver). The image is always resident in memory while some services are added to the kernel at runtime in the form of modules. Complete kernel image constitute static kernel image plus run-time loadable modules. Linux kernel configuration allows you to decide , which feature you want to include in linux kernel image , which feature you do not want to include or which service you want to make as a loadable kernel module etc.

This article will try to cover all important ones for configuring Linux kernel.

Text Based Configuration

1. Interactive Configuration

Kernel has provide an interactive text based kernel configuration utility using Makefile. If you use ‘make config’, it will configure itself. In fact, it is useful for quite experienced kernel developers and not for the beginners. The result of this command is shown below:

# make config

scripts/kconfig/conf arch/x86/Kconfig

*
* Linux Kernel Configuration
*
*
* General setup
*
Prompt for development and/or incomplete code/drivers (EXPERIMENTAL) [N/y/?] y

Local version – append to kernel release (LOCALVERSION) [] y

Automatically append version information to the version string (LOCALVERSION_AUTO) [N/y/?] y

Kernel compression mode

> 1. Gzip (KERNEL_GZIP)

  2. Bzip2 (KERNEL_BZIP2)

  3. LZMA (KERNEL_LZMA)

  4. LZO (KERNEL_LZO)

choice[1-4?]: 1

Support for paging of anonymous memory (swap) (SWAP) [N/y/?] y

System V IPC (SYSVIPC) [N/y/?] y

BSD Process Accounting (BSD_PROCESS_ACCT) [N/y/?] y

  BSD Process Accounting version 3 file format (BSD_PROCESS_ACCT_V3) [N/y/?] (NEW) y

*

* RCU Subsystem

*

RCU Implementation

> 1. Tree-based hierarchical RCU (TREE_RCU)

  2. UP-only small-memory-footprint RCU (TINY_RCU)

choice[1-2]: 1

Enable tracing for RCU (RCU_TRACE) [N/y/?] y

Tree-based hierarchical RCU fanout value (RCU_FANOUT) [32]

This command starts an interactive kernel configuration script. Once invoked, it will continuously prompts for user input at every step . User can enter any one of the four options:

  1. Yes – For building the particular feature with kernel’s static image.
  2. No – For not including the feature at all in the kernel image
  3. Module – For build this feature as loadable kernel module.
  4. ? – For help, gives brief description on the feature.

Script prompts for each and every option and expects the input for each of the options. There are so many options available so it is very tedious and time consuming way. Now you can guess the reason why it not a preferred way to configure linux kernel.

2. Predefined Configuration Target

Tell the Makefile to use predefined configuration target. There are some predefined configuration, which are: defconfig, oldconfig, randconfig, allmodconfig, allyesconfig, allnoconfig.

2.1 defconfig

Use default configuration to configure kernel.

make defconfig

It’s easy and you would not expecting much other than default parts.

This utility generates default configuration for linux kernel. This default configuration is based on the configuration options preferred and used by linux kernel maintainers on their own machines. Once the task done, you can view and modify the configuration as you wish.

2.2 oldconfig

Technically speaking, it updates the current kernel configuration by using the current .config file and prompting for any new options that have been added to the kernel.

make oldconfig

If you think your old configuration is fit to your condition, you can always use this. Like defconfig, you can view and modify the configuration once the configuration finished.

There is also a variant to this, silentoldconfig, which prints nothing to screen except a question.

2.3 randconfig

Generates a new kernel configuration with random answers to all of the different option.

make randconfig

2.4 allmodconfig

Generates a new kernel configuration in which modules are enabled whenever possible.

make allmodconfig

2.6 allyesconfig

Generates a new kernel configuration with all options set to yes.

make allyesconfig

2.7 allnoconfig

enerates a new kernel configuration with all options set to no.

make allnoconfig

Console Based Configuration

The very popular way of configuring kernel. Still using command line interface, but it’s at least graphically on terminal (using ncurses).

make menuconfig

It will opens a graphical console in which all kernel configuration options are arranged into categories. These categories are further categorized into subcategories. Just browse through and keep on selecting options until you reach the specific configuration option you need to modify.

This method is easier than the methods we have covered so far.

If you think you have it enough, you can select < Exit > to exit the configuration. You can also exit without doing any modification. A configuration, .config file, will be created / updated.

GUI Based Configuration

1. X11 Based Configuration

Using help of X window system.

make xconfig

Make xconfig is X11-based graphical configuration utility. It arranges all the configuration options into left and right pane. You can easily browse through and select different options easily.

2. GTK Based Configuration

Using GTK+ based system. Make sure you have GTK libraries installed.

make gconfig

Other

Other method to configure kernel. It doesn’t use Makefile like other methods we have discussed, but instead we directly modify the configuration file. Configuration is saved as a file “.config” without quote.

The configuration file is located in the root of the kernel source tree. It consists of some lines, usually in the format VARIABLE=value

The variable are the kernel options where the value can be y, n and other value defined for that options.

Install Kernel on Ubuntu

December 9, 2015 | Article | No Comments

One advantage of using Linux is you can change your kernel when the latest one out. For Ubuntu, you can have  a painless way to install a new kernel.

In this article, we will discuss about generic (and painless) way to install new kernel. For this case, I use Ubuntu 12.10 and the kernel we will install is 3.10 version.

How to Check Kernel Version?

To check your current linux kernel version, enter this command on terminal:

uname -r

or

cat /proc/version

Ubuntu and Precompiled Kernel

Unlike compiling kernel by yourself, Ubuntu provide you with precompiled kernel. It means, they compile the kernel for you. It might good for anyone who want to install new kernel effortlessly. However, the drawback for this precompiled kernel is the kernel is optimized for general machine. It want to address all the hardware and machine condition resulting in bigger size. Yes it can run on any machine, but might not be optimized. If you want to optimized the kernel for your machine in specific way, you might want to consider compiling kernel from source.

Obtain the Material

First, grab the material, the kernel. Go to this link, and find your preferred kernel. For example, I will use kernel labelled by v3.10-saucy.

Note that the Ubuntu release two kind of package: linux image and linux headers. The kernel itself is packaged as linux image. The linux headers are collection of headers file used for compile third party driver. Or in generic way: it is header file of linux.

For each kind, there are two package namely package for 32 bit and for 64 bit architecture. Download the kernel suitable for your Ubuntu, i.e if you use 32 bit ubuntu then choose the i686 version. Otherwise, download the amd64 version.

For v3.10-saucy, we have following options:

[32 bit]

  1. Linux Image
  2. Linux Headers

[64 bit]

  1. Linux Image
  2. Linux Headers

The rest of this article will use Kernel to refer Linux Kernel / Image you have downloaded (.deb format) while the Headers will refer to Linux Headers.

Installation

Put both Kernel and Headers into the same location. Open terminal and navigate to that directory. To install, use following commands (with root privilege):

dpkg -i *.deb

Next, reboot the system

reboot

And check the version:

uname -a

It should give you version 3.10 😀

Linux Kernel Source & Versioning

December 7, 2015 | Article | No Comments

Kernel Versioning

Anyone can build Linux kernel. Linux Kernel is provided freely on http://www.kernel.org/. From the earlier version until the latest version are available. Kernel is release regularly and use a versioning system to distinguish earlier and later kernel. To know Linux Kernel version, a simple command uname can be used. For example, I invoke this and got message

# uname -r
3.7.8-gnx-z30a

At that command output, you can see dotted decimal string 3.7.8. This is the linux kernel version. In this dotted decimal string, the first value 3 denotes major relase number. Second number 7 denotes minor release and the third value 8 is called the revision number. The major release combined with minor release is called the kernel series. Thus, I use kernel 3.7

Another string after 3.7.8 is gnx-z30a. I’m using a self-compiled kernel and add -gnx-z30a as a signature of my kernel version. Some distribution also gives their signature after the kernel, such as Ubuntu, Fedore, Red Hat, etc.

An example of building kernel can be read at this article.

Kernel Source Exploration

For building the linux kernel , you will need latest or any other stable kernel sources . For example we have taken the sources of stable kernel release version 3.8.2 . Different versions of Linux Kernel sources can be found at  http://www.kernel.org . Get latest or any stable release of kernel sources from there.

Assuming you have download the stable kernel release source on your machine, extract the source and put it to /usr/src directory.

Most of the kernel source is written in C .It is organized in various directories and subdirectories . Each directory is named after what it contains .  Directory structure of kernel may look like the below diagram.

Linux Kernel Source

Know let’s dive more into each directories.

arch/

Linux kernel can be installed on a handheld device to huge servers. It supports intel, alpha, mips, arm, sparc processor architectures . This ‘arch’ directory further contains subdirectories for a specific processor architecture. Each subdirectory contains the architecture dependent code. For example , for a PC , code will be under arch/i386 directory , for arm processor , code will be under arch/arm/arm64 directory etc.

init/

LILO or linux loader loads the kernel into memory and then control is passed to an assembler routine, arch/x86/kernel/head_x.S. This routine is responsible for hardware initialization , and hence it is architecture specific. Once hardware initialization is done , control is passed to start_kernel() routine that is defined in init/main.c . This routine is analogous to main() function in any ‘C’ program , it’s the starting point of kernel code . After the architecture specific setup is done , the kernel initialization starts and this kernel initialization code is kept under init directory. The code under this directory is responsible for proper kernel initialization that includes initialization of page addresses, scheduler, trap, irq, signals, timer, console etc.. The code under this directory is also responsible for processing the boot time command line arguments.

crypto/

This directory contains source code of different encryption algorithms , e.g. md5,sha1,blowfish,serpent and many more . All these algorithms are implemented as kernel modules . They can be loaded and unloaded at run time . We will talk about kernel modules in subsequent chapters.

documentation/

This directory contains documentation of kernel sources.

drivers/

If we understand the device driver code , it is splitted into two parts. One part communicates with user, takes commands from user , displays output to user etc. The other part communicates with the device, for example controlling the device , sending or receiving commands to and from the device etc. The part of the device driver that communicates with user is hardware independent and resides under this ‘drivers’ directory. This directory contains source code of various device drivers. Device drivers are implemented as kernel modules. As a matter of fact, majority of the linux kernel code is composed of the device drivers code , so majority of our discussion too will roam around device drivers.

This directory is further divided into subdirectories depending on the device’s driver code it contains.

drivers/block/
contains drivers for block devices,e.g. hard disks.
drivers/cdrom/
contains drivers for proprietary cd-rom drives.
drivers/char/
contains drivers for character devices , e.g. – terminals, serial port, mouse etc.
drivers/isdn/
contains isdn drivers.
drivers/net/
contains drivers for network cards.
drivers/pci/
contains drivers for pci bus access and control.
drivers/scsi/
contains drivers for scsi devices.
drivers/ide/
contains drivers for ide devices
drivers/sound/
contains drivers for various soundcards.

Another part of a device driver, that communicates with the device is hardware dependent, more specifically bus dependent. It is dependent on the type of bus which device uses for the communication. This bus specific code resides under the arch/ directory

fs/

Linux has got support for lot of file systems, e.g. ext2,ext3, fat, vfat,ntfs, nfs,jffs and more. All the source code for these different file systems supported is given in this directory under file system specific sudirectory,e.g. fs/ext2, fs/ext3 etc.

Also, linux provides a virtual file system(VFS) that acts like a wrapper to these different file systems . Linux virtual file system interface enables the user to use different file systems under one single root ( ‘/’) . Code for vfs also resides here. Data structures related to vfs are defined in include/linux/fs.h. Please take a note , it is very important header file for kernel development.

kernel/

This is one of the most important directories in kernel. This directory contains the generic code for kernel subsystem i.e. code for system calls , timers, schedulers, DMA , interrupt handling and signal handling. The architecture specific kernel code is kept under arch/*/kernel.

include/

Along with the kernel/ directory this include/ directory also is very important for kernel development .It includes generic kernel headers . This directory too contains many subdirectories . Each subdirectory contains the architecture specific header files .

ipc/

Code for all three System V IPCs(semaphores, shared memory, message queues) resides here.

lib/

Kernel’s library code is kept under this directory. The architecture specific library’s code resides under arch/*/lib.

mm/

This too is very important directory for kernel development perspective. It contains generic code for memory management and virtual memory subsystem. Again, the architecture specific code is in arch/*/mm/ directory. This part of kernel code is responsible for requesting/releasing memory, paging, page fault handling, memory mapping, different caches etc.

net/

The code for kernel’s networking subsystem resides here. It includes code for various protocols like ,TCP/IP, ARP, Ethernet, ATM, Bluetooth etc. . It includes socket implementation too , quite interesting directory to look into for networking geeks.

scripts/

This directory includes kernel build and configuration subsystem. This directory has scripts and code that is used to configure and build kernel.

security/

This directory includes security functions and SELinux code, implemented as kernel modules.

sound/

This directory includes code for sound subsystem.

module/

When the kernel is compiled , lot of code is compiled as modules which will be added later to kernel image at runtime. This directory holds all those modules. It will be empty until the kernel is built at least once.

Apart from these important directories , also there are few files under the root of kernel sources.

  • COPYING – Copyright and licensing (GNU GPL v2).
  • CREDITS – partial credits-file of people that have contributed to the Linux project.
  • MAINTAINERS – List of maintainers who maintain kernel subsystems and drivers. It also describes how to submit kernel changes.
  • Makefile – Kernel’s main or root makefile.
  • README – This is the release notes for linux kernel. it explains how to install and patch the kernel , and what to do if something goes wrong .

Documentation

We can use make documentation targets to generate linux kernel documentation. By running these targets, we can construct the documents in any of the formats like pdf, html,man page, psdocs etc.

For generating kernel documentation, give any of the commands from the root of your kernel sources.

make pdfdocs
make htmldocs
make mandocs
make psdocs

Source Browsing

Browsing source code of a large project like linux kernel can be very tedious and time consuming . Unix systems have provided two tools, ctags and cscope for browsing the codebase of large projects. Source code browsing becomes very convenient using those tools. Linux kernel has built-in support for cscope.

Using cscope, we can:

  • Find all references of a symbol
  • Find function’s definition
  • Find the caller graph of a function
  • Find a particular text string
  • Change the particular text string
  • Find a particular file
  • Find all the files that includes a particular file

Kernel Mode and Context

December 7, 2015 | Article | No Comments

User Mode and Kernel Mode

In Linux, application / software is fall into two category: user programs and kernel. Linux kernel runs under a special privileged mode compared to user applications. In this mode, kernel runs in a protected memory space and has access to entire hardware. This memory space and privileged state collectively is known as kernel space or kernel mode.

On contrary, userapplications run under user-space and have limited access to resources and hardware. User space application can’t directly access hardware or kernel space memory, but kernel has access to entire memory space. To communicate with hardware, a user application need to do system call and ask service from kernel.

Different Contexts of Kernel Code

Entire kernel code can be divided into three categories.

  1. Process Context
  2. Interrupt Context
  3. Kernel Context

Process Context

User applications can’t access the kernel space directly but there is an interface using which user applications can call the functions defined in  the kernel space. This interface is known as system call. A user application can  request for kernel services using a system call.

read() , write() calls are examples of a system call. A user application calls read() / write() , that in turn invokes sys_read() / sys_write() in the kernel space . In this case kernel code executes the request of user space application. At this point, a kernel code that executes on the request or on behalf on a userapplications is called process context code. All system calls fall in this category.

Interrupt Context

Whenever a device wants to communicate with the kernel, it sends an interrupt signal to the kernel. The moment kernel receives an interrupt request from the hardware, it starts executing some routine in the response to that interrupt request. This response routine is called as interrupt service routine or an interrupt handler. Interrupt handler routine is said to execute in the interrupt context.

Kernel Context

There is some code in the linux kernel that is neither invoked by a user application nor it is invoked by an interrupt. This code is integral to the kernel and keeps on  running always . Memory management  , process management , I/O schedulers , all that code lies in  this category. This code is said to execute in the kernel context.

Linux Kernel, Components, and Integration

December 7, 2015 | Article | No Comments

Kernel and Linux Kernel

In term of Computer Science, Kernel is the core of an Operating System. A machine (for example: personal computer) can use various hardware produced by different vendors. All can be assembled into a single machine. A hardware like processor, RAM, Hard Disk, etc is the component to build a computer. But once the computer is built, we need an operating system to make all of these hardware can be operated. The kernel does the job.

Operating System receives the request from user and processes it on user’s behalf. Requests are received by command shell or some other kind of user interface and are processed by the kernel. So, kernel acts like an engine of the operating system which enables a user to use a computer system. Shell is the outer part of the operating system that provides an interface to the user for communicating with kernel.

kernel
Kernel is bridging Applications and Hardware

Linux is one of Kernel. It is a UNIX-like kernel created by Linus Torvalds on 1991. Linux is Open Source means everyone can contribute, develop, and make their own kernel using Linus’ kernel. Nowadays, every smart system use kernel to operate and some of those system using (or maybe subset of) Linux.

Components

If we observe more, kernel can be divide into some components. The major components forming a kernel are:

  • Low Level Drivers : Architecture specific drivers and are responsible for CPU, MMU and on-board devices initialization .
  • Process Scheduler : Scheduler is responsible for fair cpu time slice allocation to different processes. Imagine you have some resource and must ensure every application can use fair amount of resource.
  • Memory Manager : Memory management system is responsible for allocating and sharing memory to different processes.
  • File System : Linux supports many file system types, e.g. – fat, ntfs, jffs and lot more. User doesn’t have to worry about the complexities of underlying file system type. For this linux provides a single interface, named as virtual file system . Using a single Virtual File System interface users can use the services of different underlying file systems. The complexities of different file systems are abstracted from the user.
  • Network Interface : This component of linux kernel provides access and control to different networking devices.
  • Device Drivers : These are high level drivers .
  • IPC : Inter Process Communication , IPC subsystem allows different processes to share data among themselves.

Fig.-1.2-Kernel-components1

Integrations

We have seen that a kernel consists of different components. Integration design tells how these different components are integrated to create kernel’s binary image.

There are mainly two integration designs used for operating system kernels , monolithic and micro. Although there are more than two but we will limit our discussion into two most used integration design.

In monolithic design all the kernel components are built together into a single static binary image . At boot up time , entire kernel gets loaded and then runs as a single process in a single address space. All the kernel components/services exist in that static kernel image . All the kernel services are running and available all the time.

Since inside the kernel everything resides in a single address space, no IPC kind of mechanism is needed for communicating between kernel services. For all these reasons monolithic kernels are high performance. Most of the unix kernels are monolithic kernels.

The disadvantage of this static kernel is lack of modularity and hotswap ability. Once the static kernel image is loaded, we can’t add/remove any component or service from the kernel. Our option is only change the hardcoded kernel. Another reason is that kernel use much memory. So, resource consumption is higher in case of monolithic kernels.

The second kind of kernel is microkernel. In microkernel a single static kernel image is not built, instead kernel image is broken down into different small services.

At boot up time , core kernel services are loaded , they run in privileged mode . Whenever some service is required , it has to get loaded for running.

Unlike monolithic kernel all services are not up and running all the time. They run as and when requested. Also, unlike monolithic kernels , services in microkernels run in separate address spaces. Therefore communication between two different services requires IPC mechanism . For all these reasons microkernels are not high performance kernels but they require less resources to run .

Linux kernel takes best of both these designs. Fundamentally it is a monolithic kernel. Entire linux kernel and all its services run as a single process , in a single address space , achieving very high performance . But it also has the capability to load / unload services at run time in the form of kernel modules .

Guide to FreeBSD Kernel Compilation

December 5, 2015 | Article | No Comments

On previous articles, we have discuss about how to compile kernel in Linux. So far we also have discuss about how to add our own system call. But how about other Operating System?

Today, most of the functionality in the FreeBSD kernel is contained in modules which can be dynamically loaded and unloaded from the kernel as necessary. This allows the running kernel to adapt immediately to new hardware or for new functionality to be brought into the kernel. This is also known as modular kernel.

Unless we have built custom kernel in FreeBSD, we are using GENERIC kernel on default. The GENERIC kernel support a wide range of hardware, contains everything we need to get machine up and running. The custom kernel can stripped down to only provide support for specific hardware of the machine, thus increasing speed and efficiency.

The common reasons for rebuilding the kernel could be fall into these category:

  1. Speed it up by taking out unused modules.
  2. Add support for new hardware
  3. Update the kernel with the new source code during a Make World.

We can also get some benefits, such as:

  1. Faster boot time. Since the kernel will only probe the hardware on the system thus make booting time faster
  2. Lower memory usage. Kernel memory remains resident in physical memory until system shut down. Thus, a minimal modules loaded can gives more memory to be used by another applications.

Now, this article will discuss about how to do a kernel recompilation on FreeBSD. On this article I will use FreeBSD 8.3 amd64 version (another version should be okay).

Finding the System Hardware

Before continuing to compile kernel, it is recommended to find and list all the system hardware of our machine. Make a list of what device is used by system so the corresponding driver can be included on custom kernel.

During boot probe, found hardware will be listed. We can use dmesg command to see what hardware had already identified by system. For example the following lines indicate that the psm driver found a mouse:

psm0: <PS/2 Mouse> irq 12 on atkbdc0
psm0: [GIANT-LOCKED]
psm0: [ITHREAD]
psm0: model Generic PS/2 mouse, device ID0

On occasion, the data from dmesg will only show system message instead of the boot probe output. In these situations, the output may be obtained by reading /var/run/dmesg.boot file.

Another method for finding hardware is to use pciconf which provides more verbose output. For example invoking command “pciconf -lv” will show ath driver located a wireless Ethernet device, such as:

[email protected]:3:0:0: card=0x058a1014 chip=0x1014168c rev=0x01 hdr=0x00
vendor = 'Atheros Communications Inc.'
device = 'AR5212 Atheros AR5212 802.11abg wireless'
class = network
subclass = ethernet

A comprehensive information can be obtained by typing man ath to read ath device manual page.

Creating the Kernel Configuration

Like all kernel compilation’s first step, we need to bring a configuration or a list of what our new kernel would be. In this article we will take a sample from our good old GENERIC config from our machine. We do this by invoking following (be sure you have root privileges):

cd /usr/src/sys/amd64/conf
cp GENERIC NEWKERNEL

If the architecture you use is not FreeBSD amd64, then replace amd64 with your corresponding architecture.

Once you have done this, open the new kernel config (the one we have copied) with text editor such as vim or ee and begin “hack” it.

The general format of a configuration file is quite simple. Each line contains a keyword and one or more arguments. For simplicity, most lines only contain one argument. Anything following a # is considered a commend and will be ignored.

An include directive is available for use in configuration file. This allows another configuration file to be included in the current one and make it easy to maintain small changes relative to an existing file.

The machine directive is telling what machine architecture we used. The argument is either amd64, i386, ia64, pc98, powerpc, or sparc64.

Exclude modules you do not needed by write ‘#’ (hash) character on the beginning of the line.

You should also change the ident directive’s argument to the name of the file. This value will be printed when the kernel boots and a good message to identify what kernel version is running now..

List of kernel configuration can be found here.

By default, when a custom kernel is compiled, all kernel modules are rebuilt as well. To update a kernel faster or to build only custom modules, we can edit /etc/make.conf before proceed to next stage. To build a kernel with a list of modules, we can write something like this:

MODULES_OVERRIDE = linux acpi sound/sound sound/driver/ds1 ntfs

In other hand, if we want to exclude list of modules from rebuilding, we can use:

WITHOUT_MODULES = linux acpi sound ntfs

After saving the edits, we can proceed to next stage.

Building and Installing

Before proceeding, it is required to have the full FreeBSD source tree installed

cd /usr/src
make buildkernel KERNCONF=NEWKERNEL
make installkernel KERNCONF=NEWKERNEL

The new kernel will be copied to /boot/kernel as /boot/kernel/kernel and the old kernel will be moved to /boot/kernel.old/kernel

Reboot

When finished customizing the kernel, save a backup copy to a location outside of /usr/src.

Reboot the machine by invoking reboot command. If the machine successfully reboot but gives errors, mostly because the kernel was compiled with the source code that is newer than that of the world.

Add New System Call to Linux 3.6.1

November 24, 2015 | Article | No Comments

As promised, this time I will show you how to add new syscall to linux 3.6.1.

Please note that the overall kernel structure in linux prior to 3.2 is different to the newer one so adding syscall in 3.6.1 would has different technique than technique discussed earlier. But by the way, the step for adding system call is similiar to previous article (step by step compile kernel 3.6.1)

If you haven’t download linux 3.6.1 you can download it from http://kernel.org/ website.

wget http://www.kernel.org/pub/linux/kernel/v3.x/linux-3.6.1.tar.xz

The reason I used linux-3.6.1.tar.xz instead of linux-3.6.1.tar.gz or linux-3.6.1.tar.bz2 is simply because of size.

Make sure you move the source to /usr/src/ directory. Do that using root access.

Now extract the source code.

tar -Jxf linux-3.6.1.tar.xz<br>cd linux-3.6.1

We can take the old configuration as our basis for creating configuration file.

cp /boot/config-2.6.35.22-generic .config

In this case I use kernel 2.6.35.22-generic. It can be different in your system so match the version number with your current kernel version.

It’s a wise way to see what we can do by invoking make. A little help could give us hint

make help

Now, to configure the config file, invoke

make menuconfig

After deciding what configuration you choose, It’s time for compilation. We will using generic way of compilation. It is the standard way provided by kernel and not platform oriented.

Now let’s jump into main subject. We will modify some files and do it sequentially and in the last we will test our new syscalls.

I’m going to create 3 syscalls, same as previous article: generate odd random-number, generate even random-number, and a dummy syscall which add input integer with 10.

Open and edit file /usr/src/linux-3.6.1/arch/x86/syscall/syscall_32.tbl. At end of file add 3 entries:

  • 350 i386 oddrandom sys_oddrandom
  • 351 i386 evenrandom sys_evenrandom
  • 352 i386 mycall sys_mycall

Did you notice number above? The entries are registered with unique numbers as seen above. Our 3 syscalls have id 350, 351, and 352. It’s easy to figure it out :). You can add more or less than this example, just remember what number your syscalls are.

Open and edit file /usr/src/linux-3.6.1/include/linux/syscalls.h. Add following entries before #endif:

  • asmlinkage unsigned int sys_oddrandom();
  • asmlinkage unsigned int sys_evenrandom();
  • asmlinkage int sys_mycall(int i);

Now create a new folder in /usr/src/linux-3.6.1/kernel, named randomsys/.

Create 4 files: sys_oddrandom.c; sys_evenrandom.c; sys_mycall.c; Makefile

Open and edit file “/usr/src/linux-3.6.1/kernel/randomsys/sys_oddrandom.c” with:

#include <linux/kernel.h>
#include <linux/syscalls.h>
#include <linux/random.h>

asmlinkage unsigned int sys_oddrandom()
{
   unsigned int v = 0;
   while( (v=get_random_int()) % 2 != 1 );
   return v;
}

Open and edit file “/usr/src/linux-3.6.1/kernel/randomsys/sys_evenrandom.c” with:

#include <linux/kernel.h>
#include <linux/syscalls.h>
#include <linux/random.h>

asmlinkage unsigned int sys_evenrandom()
{
   unsigned int v = 0;

   while( (v=get_random_int()) % 2 != 0 );

   return v;
}

Open and edit file “/usr/src/linux-3.6.1/kernel/randomsys/sys_mycall.c” with:

#include <linux/kernel.h>
#include <linux/syscalls.h>

asmlinkage int sys_mycall(int i) {
    return i+10;
}

Now open and edit “/usr/src/linux-3.6.1/kernel/randomsys/Makefile” with:

obj-y    := sys_oddrandom.o
obj-y    += sys_evenrandom.o
obj-y    += sys_mycall.o

Now open and edit “/usr/src/linux-3.6.1/kernel/Makefile“. Locate line with obj-y += power/. In my case it is on line 26th. Now add new entry below it.

obj-y += randomsys/

Next, compile our kernel and its modules. Invoke this command:

make

The process could be 1 to 4 hours depending on your system performance. For old machine like mine, it could be around 4 hours to do so. In this step the compiled kernel is stored in binary form as arc/x86/boot/bzImage file. Based on kernel headers it will compile the kernel modules (device driver, filesystem, network, etc) and generate .ko files which are kernel objects. These modules also called Loadable Kernel Modules (LKM).

Next, we will install kernel modules. to do so we can invoke

make modules_install

This step will copy all kernel modules (*.ko) to /lib/modules/<version>/kernel/ folder.

Next we will install the kernel itself. We did that by invoking

make install

This step copy the arch/x86/boot/bzImage to /boot folder and copy the .config to /boot/config-<latest version> and generate System.map file.

Next we need to create initramfs file. Next time I would write article about initramfs, but for this time just do so.

update-initramfs -c -k <version>

Here <version> can be 3.2.29 for this case.

Next we have to update the boot loader. I’m using GRUB so we have to invoke:

update-grub

This command automatically probe the kernels in /boot folder and add the entries in configuration file, grub.cfg

Restart the system and look at your bootloader entry. choose the new kernel in bootloader. Now open terminal and invoke

uname -r

Congratulations, you have build new kernel with our own syscalls now! Let’s test now.

Create 2 file: testmycall.h and testmycall.c. You can place it anywhere you want.

Now, open and edit testmycall.h

#include <linux/unistd.h>

unsigned int oddrandom() {
   return syscall(350);
}
unsigned int evenrandom() {
   return syscall(351);
}
unsigned int mycall(int i) {
   return syscall(352,i);
}

You must have known what those numbers are, aren’t you? 🙂

Now open and edit testmycall.c

#include <linux/unistd.h>
#include <sys/syscall.h>
#include "testmycall.h"

int main() {
   unsigned int v1=0,v2=0;
   int keluar=0;

   v1 = oddrandom();
   v2 = evenrandom();
   keluar = mycall(10);

   printf("v1         = %u\n",v1);
   printf("v2         = %u\n",v2);
   printf("keluar     = %d\n",keluar);

   return 0;
}

Compile and see the result by yourself 🙂

Social media & sharing icons powered by UltimatelySocial