571
1 © Copyright 2006-2004, Michael Opdenacker © Copyright 2003-2006, Oron Peled © Copyright 2004-2006 Codefidence Ltd. For full copyright information see last page. Creative Commons Attribution-ShareAlike 2.0 license Unable to handle kernel paging request at virtual address 4d1b65e8 Unable to handle kernel paging request at virtual address 4d1b65e8 pgd = c0280000 pgd = c0280000 <1>[4d1b65e8] *pgd=00000000[4d1b65e8] *pgd=00000000 Internal error: Oops: f5 [#1] Internal error: Oops: f5 [#1] Modules linked in:Modules linked in: hx4700_udc hx4700_udc asic3_base asic3_base CPU: 0 CPU: 0 PC is at set_pxa_fb_info+0x2c/0x44 PC is at set_pxa_fb_info+0x2c/0x44 LR is at hx4700_udc_init+0x1c/0x38 [hx4700_udc] LR is at hx4700_udc_init+0x1c/0x38 [hx4700_udc] pc : [<c00116c8>] lr : [<bf00901c>] Not tainted sp : c076df78 ip : 60000093 fp : c076df84 pc : [<c00116c8>] lr : [<bf00901c>] Not tainted Introduction to Embedded Linux ® Covers versions 2.4.33.2 - 2.6.18-rc4 Version 1.0

Embedded Linux Course Slides

Embed Size (px)

Citation preview

Page 1: Embedded Linux Course Slides

1© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Unable to handle kernel paging request at virtual address 4d1b65e8 Unable to handle kernel paging request at virtual address 4d1b65e8 pgd = c0280000 pgd = c0280000 <1>[4d1b65e8] *pgd=00000000[4d1b65e8] *pgd=00000000 Internal error: Oops: f5 [#1] Internal error: Oops: f5 [#1] Modules linked in:Modules linked in: hx4700_udc hx4700_udc asic3_base asic3_base CPU: 0 CPU: 0 PC is at set_pxa_fb_info+0x2c/0x44 PC is at set_pxa_fb_info+0x2c/0x44 LR is at hx4700_udc_init+0x1c/0x38 [hx4700_udc] LR is at hx4700_udc_init+0x1c/0x38 [hx4700_udc] pc : [<c00116c8>]    lr : [<bf00901c>]    Not tainted sp : c076df78  ip : 60000093  fp : c076df84 pc : [<c00116c8>]    lr : [<bf00901c>]    Not tainted 

Introduction to Embedded Linux®

Covers versions 2.4.33.2 - 2.6.18-rc4

Version 1.0

Page 2: Embedded Linux Course Slides

2© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Rights to copy

Attribution – ShareAlike 2.0You are free

to copy, distribute, display, and perform the work

to make derivative works

to make commercial use of the work

Under the following conditionsAttribution. You must give the original author credit.

Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one.

For any reuse or distribution, you must make clear to others the license terms of this work.

Any of these conditions can be waived if you get permission from the copyright holder.

Your fair use and other rights are in no way affected by the above.License text: http://creativecommons.org/licenses/by-sa/2.0/legalcode

This kit contains work by the following authors:

© Copyright 2004-2006Michael [email protected]://www.free-electrons.com

© Copyright 2003-2006Oron [email protected]://www.actcom.co.il/~oron

© Copyright 2004 – 2006Codefidence [email protected]:/www.codefidence.com

Page 3: Embedded Linux Course Slides

3© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

What is Linux?

Linux is a kernel that implements the POSIX and Single Unix Specification standards which is developed as an Open Source project.

� �Usually when one talks of installing Linux , one is referring to a Linux Distribution.

A distribution is a combination of Linux and other programs and library that form an operating system.

There exists many such distribution for various purposes, from high end servers to embedded systems.

They all share the same interface, thanks to the LSB standard

Linux runs on 24 main platforms and supports applications ranging from ccNUMA super clusters to cellular phones and micro controllers.

Linux is 15 years old, but is based on the 40 years old Unix design philosophy

Page 4: Embedded Linux Course Slides

4© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

What is Open Source?

Open Source is a way to develop software application in a distributed fashion that allows cooperation of multiple bodies to create the end product.

They don't have to be from the same company or indeed, any company.

With Open Source software the source code is published and any one can use, learn, distribute, adapt and sell the program.

An Open Source program is protected under copyright law and is licensed to it's users under a software license agreement.

It is NOT software in the public domain.

When making use of Open Source software it is imperative to understand what license governs the use of the work and what is and what is not allowed by the terms of the license.

The same thing is true for ANY external code used in a product.

Page 5: Embedded Linux Course Slides

5© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Open Source Licenses

BSDMITX11

Artistic

GPLCPLAPL

LGPL

Customer receives the

same rights I have in

the WHOLE work,

including source code.

Customer receives the

same rights I have in the

SPECIFIC PART USED,

including source code.

As long as you acknowledge by

copyright and promise not to

sue me you can do what ever

you want with the code.

Page 6: Embedded Linux Course Slides

6© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Layers in a Linux system

� Kernel

� C library

� System libraries

� Application libraries

� User programs

Kernel

C library

User programs

Page 7: Embedded Linux Course Slides

7© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Linux vs. Legacy RTOS

Kernel Shell

Process

Process

Process

Process

Process

Library

RTOS

RTOS are like the Linux kernel:Single program with single memory space that manages memory, scheduling and interrupts.

Linux also has user tasks that run in their own memory space. One of them is the shell.

Page 8: Embedded Linux Course Slides

8© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

This course

KernelShell

Process

Process

Process

Process

Process

Library

In this course we will go from the shell, through the system libraries and applications and unto the kernel.

Page 9: Embedded Linux Course Slides

9© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

The Unix and GNU / Linux command line

Unix File System

Page 10: Embedded Linux Course Slides

10© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Everything is a file

Regular files

DirectoriesDirectories are just files listing a set of files

Symbolic linksFiles referring to the name of another file

Devices and peripheralsRead and write from devices as with regular files

PipesUsed to cascade programscat *.log | grep error

SocketsInter process communication

Almost everything in Unix is a file!

Page 11: Embedded Linux Course Slides

11© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

File names

File name features since the beginning of Unix

Case sensitive

No obvious length limit

Can contain any character (including whitespace, except /).File types stored in the file (“magic numbers”).File name extensions not needed and not interpreted. Just used for user convenience.

File name examples:README .bashrc Windows Buglistindex.htm index.html index.html.old

Page 12: Embedded Linux Course Slides

12© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

File paths

A path is a sequence of nested directories with a file or directory at the end, separated by the / character

Relative path: documents/fun/microsoft_jokes.htmlRelative to the current directory

Absolute path: /home/bill/bugs/crash9402031614568

/ : root directory.Start of absolute paths for all files on the system (even for files on removable devices or network shared).

Page 13: Embedded Linux Course Slides

13© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

GNU / Linux filesystem structure (1)

Not imposed by the system. Can vary from one system to the other, even between two GNU/Linux installations!

/ Root directory/bin/ Basic, essential system commands/boot/ Kernel images, initrd and configuration files/dev/ Files representing devices

/dev/hda: first IDE hard disk/etc/ System configuration files/home/ User directories/lib/ Basic system shared libraries

Page 14: Embedded Linux Course Slides

14© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

GNU / Linux filesystem structure (2)

/lost+found Corrupt files the system tried to recover/mnt/ Mounted filesystems

/mnt/usbdisk/, /mnt/windows/ .../opt/ Specific tools installed by the sysadmin

/usr/local/ often used instead/proc/ Access to system information

/proc/cpuinfo, /proc/version .../root/ root user home directory/sbin/ Administrator-only commands/sys/ System and device controls

(cpu frequency, device power, etc.)

Page 15: Embedded Linux Course Slides

15© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

GNU / Linux filesystem structure (3)

/tmp/ Temporary files/usr/ Regular user tools (not essential to the system)

/usr/bin/, /usr/lib/, /usr/sbin.../usr/local/ Specific software installed by the sysadmin

(often preferred to /opt/)/var/ Data used by the system or system servers

/var/log/, /var/spool/mail (incoming mail), /var/spool/lpd (print jobs)...

Page 16: Embedded Linux Course Slides

16© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

The Unix and GNU / Linux command line

Shells and file handling

Page 17: Embedded Linux Course Slides

17© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Command line interpreters

Shells: tools to execute user commands

Called “shells” because they hide the details on the underlying operating system under the shell's surface.

Commands are input in a text terminal, either a window in a graphical environment or a text-only console.

Results are also displayed on the terminal. No graphics are needed at all.

Shells can be scripted: provide all the resources to write complex programs (variable, conditionals, iterations...)

Page 18: Embedded Linux Course Slides

18© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

The Unix and GNU / Linux command line

Task control

Page 19: Embedded Linux Course Slides

19© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Full control on tasks

Since the beginning, Unix supports true preemptive multitasking.

Ability to run many tasks in parallel, and abort them even if they corrupt their own state and data.

Ability to choose which programs you run.

Ability to choose which input your programs takes, and where their output goes.

Page 20: Embedded Linux Course Slides

20© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Processes

“Everything in Unix is a fileEverything in Unix that is not a file is a process”

Processes

Instances of a running programs

Several instances of the same program can run at the same time

Data associated to processes:Open files, allocated memory, stack, process id, parent, priority, state...

Page 21: Embedded Linux Course Slides

21© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Running jobs in background

Same usage throughout all the shells

Useful

For command line jobs which output can be examined later, especially for time consuming ones.

To start graphical applications from the command line and then continue with the mouse.

Starting a task: add & at the end of your line:

find_prince_charming --cute --clever --rich &

Page 22: Embedded Linux Course Slides

22© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Background job control

jobsReturns the list of background jobs from the same shell

[1]- Running ~/bin/find_meaning_of_life --without-god &[2]+ Running make mistakes &

fgfg %<n>Puts the last / nth background job in foreground mode

Moving the current task in background mode:[Ctrl] Zbg

kill %<n>Aborts the nth job.

Page 23: Embedded Linux Course Slides

23© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Job control example

> jobs[1]- Running ~/bin/find_meaning_of_life --without-god &[2]+ Running make mistakes &

> fgmake mistakes

> [Ctrl] Z[2]+ Stopped make mistakes

> bg[2]+ make mistakes &

> kill %1[1]+ Terminated ~/bin/find_meaning_of_life --without-god

Page 24: Embedded Linux Course Slides

24© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Listing all processes

... whatever shell, script or process they are started from

ps -uxLists all the processes belonging to the current user

ps -aux (Note: ps -edf on System V systems)Lists all the processes running on the systemps -aux | grep bart | grep bashUSER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMANDbart 3039 0.0 0.2 5916 1380 pts/2 S 14:35 0:00 /bin/bashbart 3134 0.0 0.2 5388 1380 pts/3 S 14:36 0:00 /bin/bashbart 3190 0.0 0.2 6368 1360 pts/4 S 14:37 0:00 /bin/bashbart 3416 0.0 0.0 0 0 pts/2 RW 15:07 0:00 [bash]

PID: Process idVSZ: Virtual process size (code + data + stack)RSS: Process resident size: number of KB currently in RAMTTY: TerminalSTAT: Status: R (Runnable), S (Sleep), D (Uninterrupted sleep), Z (Zombie)...

Page 25: Embedded Linux Course Slides

25© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Live process activity

top - Displays most important processes, sorted by cpu percentage

top - 15:44:33 up 1:11, 5 users, load average: 0.98, 0.61, 0.59Tasks: 81 total, 5 running, 76 sleeping, 0 stopped, 0 zombieCpu(s): 92.7% us, 5.3% sy, 0.0% ni, 0.0% id, 1.7% wa, 0.3% hi, 0.0% siMem: 515344k total, 512384k used, 2960k free, 20464k buffersSwap: 1044184k total, 0k used, 1044184k free, 277660k cached

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND3809 jdoe 25 0 6256 3932 1312 R 93.8 0.8 0:21.49 bunzip22769 root 16 0 157m 80m 90m R 2.7 16.0 5:21.01 X3006 jdoe 15 0 30928 15m 27m S 0.3 3.0 0:22.40 kdeinit3008 jdoe 16 0 5624 892 4468 S 0.3 0.2 0:06.59 autorun3034 jdoe 15 0 26764 12m 24m S 0.3 2.5 0:12.68 kscd3810 jdoe 16 0 2892 916 1620 R 0.3 0.2 0:00.06 top

You can change the sorting order by typingM: Memory usage, P: %CPU, T: Time.

You can kill a task by typing k and the process id.

Page 26: Embedded Linux Course Slides

26© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Killing processes (1)

kill <pids>Sends an abort signal to the given processes. Lets processes save data and exit by themselves. Should be used first. Example:kill 3039 3134 3190 3416

kill -9 <pids>Sends an immediate termination signal. The system itself terminates the processes. Useful when a process is really stuck (doesn't answer to kill -1).

kill -9 -1Kills all the processes of the current user. -1: means all processes.

Page 27: Embedded Linux Course Slides

27© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Killing processes (2)

killall [-<signal>] <command>Kills all the jobs running <command>. Example:killall bash

Page 28: Embedded Linux Course Slides

28© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Sequential commands

Can type the next command in your terminal even when the current one is not over.

Can separate commands with the ; symbol:echo “I love thee”; sleep 10; echo “ not”

Conditionals: use || (or) or && (and):more God || echo “Sorry, God doesn't exist”Runs echo only if the first command fails

ls ~sd6 && cat ~sd6/* > ~sydney/recipes.txtOnly cats the directory contents if the ls command succeeds (means read access).

Page 29: Embedded Linux Course Slides

29© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Measuring elapsed time

time find_expensive_housing --near<...command output...>real 0m2.304s (actual elapsed time)user 0m0.449s (CPU time running program code)sys 0m0.106s (CPU time running system calls)

real = user + sys + waitingwaiting = I/O waiting time + idle time (running other tasks)

Page 30: Embedded Linux Course Slides

30© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Environment variables

Shells let the user define variables.They can be reused in shell commands.Convention: lower case names

You can also define environment variables: variables that are also visible within scripts or executables called from the shell.Convention: upper case names.

envLists all defined environment variables and their value.

Page 31: Embedded Linux Course Slides

31© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Shell variables examples

Shell variables (bash)

projdir=/home/marshall/coolstuffls -la $projdir; cd $projdir

Environment variables (bash)

cd $HOME

export DEBUG=1./find_extraterrestrial_life(displays debug information if DEBUG is set)

Page 32: Embedded Linux Course Slides

32© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

The Unix and GNU / Linux command line

System administration basics

Page 33: Embedded Linux Course Slides

33© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

File ownership

chown -R sco /home/linux/src (-R: recursive)Makes user sco the new owner of all the files in /home/linux/src.

chgrp -R empire /home/askywalkerMakes empire the new group of everything in /home/askywalker.

chown -R borg:aliens usss_entreprise/chown can be used to change the owner and group at the same time.

Page 34: Embedded Linux Course Slides

34© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Shutting down

shutdown -h +5 (-h: halt)Shuts the system down in 5 minutes.Users get a warning in their consoles.

shutdown -r now (-r: reboot)

init 0Another way to shutdown (used by shutdown).

init 6Another way to reboot (used by shutdown).

[Ctrl][Alt][Del]Also works on GNU/Linux (at least on PCs!).

Page 35: Embedded Linux Course Slides

35© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Network setup (1)

ifconfig -aPrints details about all the network interfaces available on your system.

ifconfig eth0Lists details about the eth0 interface

ifconfig eth0 192.168.0.100Assigns the 192.168.0.100 IP addressto eth0 (1 IP address per interface).

ifconfig eth0 downShuts down the eth0 interface(frees its IP address).

Page 36: Embedded Linux Course Slides

36© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Network setup (2)

route add default gw 192.168.0.1Sets the default route for packets outside the local network. The gateway (here 192.168.0.1) is responsible for sending them to the next gateway, etc., until the final destination.

routeLists the existing routes

route del defaultroute del <IP>Deletes the given routeUseful to redefine a new route.

Page 37: Embedded Linux Course Slides

37© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Network testing

ping freshmeat.netping 192.168.1.1Tries to send packets to the given machine and get acknowledgment packets in return.

PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.64 bytes from 192.168.1.1: icmp_seq=0 ttl=150 time=2.51 ms64 bytes from 192.168.1.1: icmp_seq=1 ttl=150 time=3.16 ms64 bytes from 192.168.1.1: icmp_seq=2 ttl=150 time=2.71 ms64 bytes from 192.168.1.1: icmp_seq=3 ttl=150 time=2.67 ms

When you can ping your gateway, your network interface works fine.

When you can ping an external IP address, your network settings are correct!

Page 38: Embedded Linux Course Slides

38© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Network setup summary

Only for simple cases with 1 interface, no dhcp server...

Connect to the network (cable, wireless card or device...)

Identify your network interface:ifconfig -a

Assign an IP address to your interface (assuming eth0)ifconfig eth0 192.168.0.100 (example)

Add a route to your gateway (assuming 192.168.0.1) for packets outside the network:route add default gw 192.168.0.1

Page 39: Embedded Linux Course Slides

39© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Name resolution

Your programs need to know what IP address corresponds to a given host name (such as kernel.org)

Domain Name Servers (DNS) take care of this.

You just have to specify the IP address of 1 or more DNS servers in your /etc/resolv.conf file:nameserver 217.19.192.132nameserver 212.27.32.177

The changes takes effect immediately!

Page 40: Embedded Linux Course Slides

40© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Creating filesystems

Examples

mkfs.ext2 /dev/sda1Formats your USB key (/dev/sda1: 1st partition raw data) in ext2 format.

mkfs.ext2 -F disk.imgFormats a disk image file in ext2 format

mkfs.vfat -v -F 32 /dev/sda1 (-v: verbose)Formats your USB key back to FAT32 format.

mkfs.vfat -v -F 32 disk.imgFormats a disk image file in FAT32 format.

Blank disk images can be created a in the below example:dd if=/dev/zero of=disk.img bs=1024 count=65536

Page 41: Embedded Linux Course Slides

41© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Mounting devices (1)

To make filesystems on any device (internal or external storage) visible on your system, you have to mount them.

The first time, create a mount point in your system:mkdir /mnt/usbdisk (example)

Now, mount it:mount -t vfat /dev/sda1 /mnt/usbdisk/dev/sda1: physical device-t: specifies the filesystem (format) type(ext2, ext3, vfat, reiserfs, iso9660...)

Page 42: Embedded Linux Course Slides

42© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Mounting devices (2)

Lots of mount options are available, in particular to choose permissions or the file owner and group... See the mount manual page for details.

Mount options for each device can be stored in the /etc/fstab file.

You can also mount a filesystem image stored in a regular file (loopback devices)

Useful to access the contents of an ISO cdrom image without having to burn it.

Useful to create a Linux partition on a hard disk with only Windows partitions

cp /dev/sda1 usbkey.imgmount -o loop -t vfat usbkey.img /mnt/usbdisk

Page 43: Embedded Linux Course Slides

43© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Listing mounted filesystems

Just use the mount command with no argument:

/dev/hda6 on / type ext3 (rw,noatime)none on /proc type proc (rw,noatime)none on /sys type sysfs (rw)none on /dev/pts type devpts (rw,gid=5,mode=620)usbfs on /proc/bus/usb type usbfs (rw)/dev/hda4 on /data type ext3 (rw,noatime)none on /dev/shm type tmpfs (rw)/dev/hda1 on /win type vfat (rw,uid=501,gid=501)none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)

Or display the /etc/mtab file(same result, updated by mount and umount each time they are run)

Page 44: Embedded Linux Course Slides

44© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Unmounting devices

umount /mnt/usbdiskCommits all pending writes and unmounts the given device, which can then be removed in a safe way.

To be able to unmount a device, you have to close all the open files in it:

Close applications opening data in the mounted partition

Make sure that none of your shells have a working directory in this mount point.

You can run the lsof command (list open files) to view which processes still have open files in the mounted partition.

Page 45: Embedded Linux Course Slides

45© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Free Software tools for embedded systems

C library for the target deviceC library options

Page 46: Embedded Linux Course Slides

46© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

glibc

http://www.gnu.org/software/libc/

License: LGPL

C library from the GNU project

Designed for performance, standards compliance and portability

Found on all GNU / Linux host systems

Quite big for small embedded systems: about 1.7MB on Familiar Linux iPAQs (libc: 1.2 MB, libm: 500 KB)

Page 47: Embedded Linux Course Slides

47© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

uClibc

http://www.uclibc.org/ for CodePoet Consulting

License: LGPL

Lightweight C library for small embedded systems, with most features though.

The whole Debian Woody was ported to it...You can assume it satisfied most needs!

Example size (arm): approx. 400KB (libuClibc: 300 KB, libm: 55KB)

Page 48: Embedded Linux Course Slides

48© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Honey, I shrunk the programs!

C program Compiled with shared libraries Compiled staticallyglibc uClibc glibc uClibc

Plain “hello world” 4.6 K 4.4 K 475 K 25 K

Busybox 245 K 231 K 843 K 311 K

Page 49: Embedded Linux Course Slides

49© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

C library options - Summary

GNU C library (glibc)Designed for performance compliance with standards.Best for servers and desktops.

uClibcHighly compatible, but implemented for small embedded systems with little storage space and RAM

Page 50: Embedded Linux Course Slides

50© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Free Software tools for embedded systems

GNU / Linux workstationCross-compiling toolchains

Page 51: Embedded Linux Course Slides

51© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Standalone toolchain build

Building a cross-compiling toolchain by yourself is a difficult and painful task! Can take days or weeks!

Lots of details to learn. Several components to build (building gcc twice: once for gcc + once for compilers that need the C library).

Lots of decisions to make (such as glibc version and configuration for your platform)

Need kernel headers and glibc sources

Need to be familiar with current gcc issues and patches on your platform

Useful to be familiar with building and configuring tools

http://www.aleph1.co.uk/armlinux/docs/toolchain/toolchHOWTO.pdf can show you how fun it can be!

Page 52: Embedded Linux Course Slides

52© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Get a precompiled toolchain

Can get one from several locations... Just need to know where!

Caution

Toolchains are not always relocatable! Install them in/usr/local/<arch> if they were built for this location.

Make sure the toolchain you pick suits your needs:CPU, endianism, C library and compiler versions...

Page 53: Embedded Linux Course Slides

53© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

uClibc toolchains

Free Electrons uClibc toolchainshttp://free-electrons.com/community/tools/uclibc

Run on i386 GNU/Linux

Supported platformsarm, armeb, i386, m68k, ppc, mips, mipsel, sh

Quickly updated at each new uClibc release!

Page 54: Embedded Linux Course Slides

54© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Platform specific toolchains

ARM

Code Sourcery (glibc only, used by many):http://www.codesourcery.com/gnu_toolchains/arm/Also available for Solaris and Windows workstations.

ftp://ftp.handhelds.org/projects/toolchain/ (glibc only)

MIPS

http://www.linux-mips.org/wiki/Toolchains (useful links)

Page 55: Embedded Linux Course Slides

55© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Toolchain building utilities

Buildroot: http://buildroot.uclibc.org/

Dedicated Makefile to build uClibc based toolchains and even entire root filesystems.

Downloads sources and applies patches.

Crosstool: http://www.kegel.com/crosstool/

Dedicated script to build glibc based toolchainsDoesn’t support uClibc yet.

Downloads sources and applies patches.

Page 56: Embedded Linux Course Slides

56© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

gcc / glibc / binutils / kernel versions

Crosstool build reports: http://kegel.com/crosstool/crosstool-0.38/buildlogs/

Can help you to find a working

combination of gcc, glibc,

binutils and kernel

headers versions!

Page 57: Embedded Linux Course Slides

57© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

PTXdist

http://www.pengutronix.de/software/ptxdist_en.html - A cross-compiling toolkit project

Makes it easier to cross-compile a complete embedded Linux system

Supports 10 different platforms.

Uses crosstool to build cross compiler toolchains

Supported libraries: glibc, uClibc

uClibc support is still experimental/buggy...

Supports around 200 different packages.

Page 58: Embedded Linux Course Slides

58© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

PTXdist Screenshots

Page 59: Embedded Linux Course Slides

59© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Toolchains - useful resources

CE Linux Forum's toolchain pagehttp://tree.celinuxforum.org/CelfPubWiki/ToolChains

Page 60: Embedded Linux Course Slides

60© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Cross-compiling toolchains - Summary

Building a toolchain by yourselfTough and very long to master.

Ready-to-use toolchainsAvailable from several locations for most platforms.

Tools to build toolchains: Buildroot and Crosstool.Make it easy to create a toolchain for your exact needs.

Build systems: PTXdistHelp you to create and populate root filesystem.

Page 61: Embedded Linux Course Slides

61© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Free Software tools for embedded systems

GNU / Linux workstationEmulators

Page 62: Embedded Linux Course Slides

62© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Usefulness of emulators

Of course, can be used to run another system on top of another.

Can be used to test kernel and applications ahead of time on a workstation without the cost of a development board.

Make the operating system easier to debug than with actual hardware. If the OS freezes, just restart the emulator.

Can provide debugger and tracing capabilities

However, often emulate only the processor and a few devices at best. Don't replace the real hardware or a development board.

Page 63: Embedded Linux Course Slides

63© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

qemu

http://qemu.orgFast processor emulatorusing a portable dynamic translator.

2 operating modes

Full system emulation: processor and various peripheralsSupported: x86, x86_64, ppc, arm, sparc, mips

User mode emulation (Linux host only): can run applications compiled for another CPU. Supported: x86, ppc, arm, sparc, mips

Page 64: Embedded Linux Course Slides

64© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

qemu examples (1)

User emulation

Easy to run Busybox for arm on i386 GNU / Linux:qemu-arm -L /usr/local/arm/3.3.2 \/home/bart/arm/busybox-1.00-pre8/busybox ls

-L: target C library binaries path (here cross-compiler toolchain path)

Page 65: Embedded Linux Course Slides

65© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

qemu examples (2)

System emulation

Even easier to run: (x86 example)qemu linux.img

linux.img: full partition image including the kernelOther options let the user choose an external kernel, kernel command line options, and many more!

Lots of images of free operating systems available on http://free.oszoo.org! Of course, qemu can also be used to run Windows or MacOS X on your computer (provided you have a legal copy of the system).

Page 66: Embedded Linux Course Slides

66© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

ARM emulators

Only Free Software, of course!

SkyEye: http://skyeye.sourceforge.netEmulates several ARM platforms (AT91, Xscale...) and can boot several operating systems (Linux, uClinux, and others)

Softgun: http://softgun.sourceforge.netVirtual ARM system with many virtual on-board peripherals. Boots Linux.

SWARM - Software ARM - arm7 emulatorhttp://www.cl.cam.ac.uk/~mwd24/phd/swarm.htmlCan run uClinux

Page 67: Embedded Linux Course Slides

67© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Other emulators

ColdFire emulatorhttp://www.slicer.ca/coldfire/Can boot uClinux

Page 68: Embedded Linux Course Slides

68© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Emulators - Summary

System emulatorsUseful to experiment with a full system, including the kernelqemu: x86, x86_64, arm, sparc, ppc, mipsSkyEye: several arm architectures

User emulatorsUseful to run or debug user space binaries for other CPUsqemu: x86, arm, sparc, ppc, mips

Page 69: Embedded Linux Course Slides

69© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Free Software tools for embedded systems

Tools for the target deviceBusybox

Page 70: Embedded Linux Course Slides

70© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

General purpose toolbox: busybox

http://www.busybox.net/ from Codepoet Consulting

Most Unix command line utilities within a single executable! Even includes a web server!

Sizes less than < 500 KB (statically compiled with uClibc) or less than 1 MB (statically compiled with glibc)

Easy to configure which features to include

The best choice for

Initrds with complex scripts

Small embedded systems with little RAM or ROM.

Page 71: Embedded Linux Course Slides

71© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Busybox commands!

addgroup, adduser, adjtimex, ar, arping, ash, awk, basename, bunzip2, bzcat, cal, cat, chgrp, chmod, chown, chroot, chvt, clear, cmp, cp, cpio, crond, crontab, cut, date, dc, dd, deallocvt, delgroup, deluser, devfsd, df, dirname, dmesg, dos2unix, dpkg, dpkg-deb, du, dumpkmap, dumpleases, echo, egrep, env, expr, false, fbset, fdflush, fdformat, fdisk, fgrep, find, fold, free, freeramdisk, fsck.minix, ftpget, ftpput, getopt, getty, grep, gunzip, gzip, halt, hdparm, head, hexdump, hostid, hostname, httpd, hush, hwclock, id, ifconfig, ifdown, ifup, inetd, init, insmod, install, ip, ipaddr, ipcalc, iplink, iproute, iptunnel, kill, killall, klogd, lash, last, length, linuxrc, ln, loadfont, loadkmap, logger, login, logname, logread, losetup, ls, lsmod, makedevs, md5sum, mesg, mkdir, mkfifo, mkfs.minix, mknod, mkswap, mktemp, modprobe, more, mount, msh, mt, mv, nameif, nc, netstat, nslookup, od, openvt, passwd, patch, pidof, ping, ping6, pipe_progress, pivot_root, poweroff, printf, ps, pwd, rdate, readlink, realpath, reboot, renice, reset, rm, rmdir, rmmod, route, rpm, rpm2cpio, run-parts, rx, sed, seq, setkeycodes, sha1sum, sleep, sort, start-stop-daemon, strings, stty, su, sulogin, swapoff, swapon, sync, sysctl, syslogd, tail, tar, tee, telnet, telnetd, test, tftp, time, top, touch, tr, traceroute, true, tty, udhcpc, udhcpd, umount, uname, uncompress, uniq, unix2dos, unzip, uptime, usleep, uudecode, uuencode, vconfig, vi, vlock, watch, watchdog, wc, wget, which, who, whoami, xargs, yes, zcat

Page 72: Embedded Linux Course Slides

72© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Compiling busybox

Get the latest stable sources from http://busybox.net

Configure busybox (creates a .config file):make menuconfig

Compile it:make

Install it:make installLogged as root, mount the root fs image (e.g. /mnt/rootfs)rsync -a _install/ /mnt/rootfs/(the / characters are needed!)

Page 73: Embedded Linux Course Slides

73© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

logread

Part of Busybox.

Shows the messages from syslogd (using its circular buffer).

Replaces /var/log/messages. Reduces space and complexity (no need to rotate this file).

Use logread -f to output data as the log grows.

Another possibility: use the dmesg command.

Page 74: Embedded Linux Course Slides

74© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

tinylogin

http://tinylogin.busybox.net/

Suite of tiny Unix utilities for

Handling logging

Being authenticated

Changing passwords

Maintaining users and groups.Provides shadow password supportto enhance system security.

Tools and sizes 0K /usr/sbin/addgroup24K /usr/sbin/adduser16K /sbin/getty36K /bin/login28K /usr/bin/passwd24K /bin/su12K /sbin/sulogin

Commands already provided by Busybox. Just useful if your system doesn't use busybox.

Page 75: Embedded Linux Course Slides

75© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Free Software tools for embedded systems

Tools for the target devicehttp and ssh servers

Page 76: Embedded Linux Course Slides

76© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

ssh server and client: dropbear

http://matt.ucc.asn.au/dropbear/dropbear.html

Very small memory footprint ssh server for embedded systems, compared to OpenSSH.

Satisfies most needs. Both client and server!

Useful to:

Get a remote console on the target device

Copy files to and from the target device

rsync files with the target device

Page 77: Embedded Linux Course Slides

77© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

thttpd

Tiny/Turbo/Throttling HTTP serverhttp://acme.com/software/thttpd/

SimpleImplements the HTTP/1.1 minimum (or just a little more)Simple to configure and run.

SmallExecutable size: 88K (version 2.25b), Apache 2.0.52: 264KVery low memory consumption: does not fork and very careful about memory consumption.

PortableCompiles cleanly on most Unix-like operating systems

FastAbout as fast as full-featured servers. Much faster on very high loads (because reduces the server load for the same amount of work)

SecureDesigned to protect the webserver machine from attacks.

Page 78: Embedded Linux Course Slides

78© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Other web servers (1)

Busybox http server: http://busybox.netTiny: only adds 12 K to Busybox 1.01 (compiled statically with uClibc)!Sufficient features for many devices with a web interface,including CGI and http authentication support.License: GPL

KLone: http://koanlogic.com/kl/cont/gb/html/klone.htmlLightweight but full featured web server for embedded systems.Can enclose dynamic (written in C/C++ <% code %>) and compressed content all in an executable of an approximate size of 150 KB.License: Dual GPL / Commercial.See also http://linuxdevices.com/news/NS8234701895.html

Page 79: Embedded Linux Course Slides

79© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Other web servers (2)

Boa: http://www.boa.org/Designed to be simple, fast and secure.Unlike thttpd, no particular care for memory or disk footprint though.Embedded systems: pretty popular, though not targeted by developers.

lighthttpd: http://lighttpd.netLow footprint server good at managing high loads.May be useful in embedded systems too.

Page 80: Embedded Linux Course Slides

80© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Free Software tools for embedded systems

GNU / Linux workstationCommercial toolsets

Page 81: Embedded Linux Course Slides

81© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Commercial toolsets

Caution: commercial doesn't mean proprietary!

Vendors play fair with the GPL and do make their source code available to their users, and most of the time, to the community.

As long as they distribute the sources to their users, the GPL doesn't require vendors to share their sources with any third party.

No issue with all the GPL sources developed by or with the community.

Graphical toolkits developed by the vendors look proprietary. Their licenses are not advertised on their websites! You have to be a customer to know or get a free preview kit to know.

Page 82: Embedded Linux Course Slides

82© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Commercial toolset strengths

Technical advantages

Well tested and supported kernel and tool versions

Including early patches not supported by the mainstream kernel yet

Complete development tool sets: kernels, toolchains, utilities, binaries for impressive lists of target platforms

Integrated utilities for automatic kernel image, initrd and filesystem generation.

Graphical developments tools

Development tools available on multiple platforms: GNU / Linux, Solaris, Windows...

Support services

Useful if you don't have your own support resources

Long term support commitment, even for versions considered as obsolete by the community, but not by your users!

Page 83: Embedded Linux Course Slides

83© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Montavista

http://www.mvista.com/

The market leader

Employs some of the most active kernel hackers, in particular on the arm platform

All kernel development shared with the community kernel core and drivers (Linux 2.6 example: preemption option, many drivers...)

Graphical development tools are proprietary

Page 84: Embedded Linux Course Slides

84© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

TimeSys

http://timesys.com

Similar toolset offering as other vendors.Great flexibility available to their LinuxLinkTM subscribers

Community friendly: share very interesting and generic technical whitepapers and articles.

Free Software BSPs (Board Support Packages) available

Linux soft and hard real-time OS product

Development tools seem to be proprietary

Page 85: Embedded Linux Course Slides

85© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Traditional RTOS vendors

Traditional RTOS expertise. Good for hard real-time needs!

Offer the same development tools for their proprietary RTOS and their Linux offering. Possible to switch from one to the other if needed.

Though they are big players, they do not seem to participatemuch in the development of Linux.

WindRiver: http://windriver.com/linuxThe makers of VxWorks operating system. Now advertise both systems.

LynuxWorks BlueCat: http://lynuxworks.com/products/bluecat/Mainly seems to be a way of surfing the Linux wave and attracting customers to their LynxOS RTOS (API compatible with Linux).

Page 86: Embedded Linux Course Slides

86© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Other vendors (1)

http://www.metrowerks.com/Now owns LineoNow owned by Freescale

Similar tool offering, experience and skills from Lineo.

Embedded applications portfolio. Example: OpenPDA.

Only advisable for Freescale customers: now mainly focusing on Freescale platforms and giving up support for competing architectures.

http://koansoftware.com

Makers of Klinux (http://klinux.org), a GPL embedded Linux distribution for industrial applications.

Klinux supports i386 and popular arm platforms. Other platforms supported upon request.

Includes several graphical toolkits and supports hard real-time (RTAI).

Unfortunately, Klinux is GPL but not available for public download.

Page 87: Embedded Linux Course Slides

87© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Other vendors (2)

http://sysgo.com

ELinOS development toolset,in particular based on Eclipse and the Linux Trace Toolkit.

Includes FreeToolBox, a freely downloadable compiling and rootfs creating toolchain.

Supports i386, arm and ppc.

Real-time support with RTAI

Page 88: Embedded Linux Course Slides

88© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Commercial toolsets - Summary

Major vendorsMontaVista, TimeSys (MetroWerks exiting the market)Involved in Linux development

Smaller vendorsKoan, Sysgo...Trying to differenciate their products

Traditional RTOS vendorsWindRiver, LynuxWorksForced to support Linux to retain market share.Strong real-time expertise but lack of community involvement

Page 89: Embedded Linux Course Slides

89© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Free Software tools for embedded systems

Tools for the target devicePrecompiled packages, distributions

Page 90: Embedded Linux Course Slides

90© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Distributions

Distribute ready to use root filesystems.Can be used by any binary compatible platform.Example: running Familiar Linux on a mobile phone!

Can be reused even on an early development phase.No need to create your root filesystem from scratch!

Easy to upgrade, remove or add applications through binary packages.

Page 91: Embedded Linux Course Slides

91© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded distributions (1)

arm little endian:

Familiar http://familiar.handhelds.org/Targets PDAs and webpads (Siemens Simpad...)

IpkgFind: http://ipkgfind.handhelds.org/References lots of arm binary packages for ipkg based distributions (such as Familiar / OpenZaurus)Search by category, keyword or name.

Page 92: Embedded Linux Course Slides

92© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded distributions (2)

Emdebian: http://emdebian.sourceforge.net

Supports all embedded platforms

Leverages standard Debian package descriptions and sources, but adapts them for embedded systems: uClibc usage, reduced package size (no documentation), removed dependencies, configured with less options...

Packages not available yet, but makes it possible to build packages using Debian utilities (such as dpkg-cross)

Unfortunately, lacking momentum in recent months

Page 93: Embedded Linux Course Slides

93© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Ready-made root filesystems

Very useful to start porting work. Contain C library, and minimum apps.

uClibc

http://www.uclibc.org/toolchains.html (i386, arm, mipsel)Images include a native gcc toolchain

ARM

http://www.arm.com/linux/linux_download.htmlInclude kernel image, bootloader, and rootfs (cramfs or packages)

Other architectures

If some readers know more useful links, they are welcome!

Page 94: Embedded Linux Course Slides

94© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Buildroot

http://buildroot.uclibc.org/

Tool to automatically build a ready-made uClibc rootfs with basic applications and a development toolchain. Useful in early development.

Can be used to build only uClibc toolchains.

Supports lots of architectures

Automatically downloads source packages

Very easy to use: just run: make

Page 95: Embedded Linux Course Slides

95© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Linux porting projects

Useful to find patches, binaries, documentation, toolchains...Only ports for embedded systems are listed

arm: http://www.arm.linux.org.uk/

m68k: http://www.linux-m68k.org/

mips: http://www.linux-mips.org/

ppc: http://penguinppc.org/embedded/

sh: http://linuxsh.sourceforge.net/

xtensa: http://xtensa.sourceforge.net/

Page 96: Embedded Linux Course Slides

96© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Conclusion

Commercial distributions and toolsets

Best if you don't have your own support resources and have a sufficient budget

Really help focusing on your real job: making an embedded device.

You can even subcontract driver development to the vendor

Community distributions and tools

Best if you are on a tight budget

Best if you are willing to build your own embedded Linux expertise and train your own support resources.

In any case, your products are based on Free Software!

Page 97: Embedded Linux Course Slides

97© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Coding Embedded Linux Applications

Writing Code

Page 98: Embedded Linux Course Slides

98© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Hello World!

#include <stdio.h>

int main(int argc, char **argv)

{

int i=1;

printf ("Hello World! %d\n", i);

return 0;

}

Page 99: Embedded Linux Course Slides

99© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

A simple Makefile

CC=/usr/local/arm/2.95.3/bin/arm-linux-gcc

CFLAGS=-g

LDFLAGS=-lpthreads

.PHONY: clean all

all: test

clean:

@rm -f *.o *~ test

Page 100: Embedded Linux Course Slides

100© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Creating Processes using fork()

pid_t pid;

if (pid = fork() ) {

int status;

printf("I'm the parent!\n");

wait(&status);

if( WIFEXITED(status) )

printf("Child exist with status of %d\n", WEXITSTATUS(status));

} else {

printf("I'm the child!\n");

exit(0);

}

Page 101: Embedded Linux Course Slides

101© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Creating Processes (2)

pid_t pid;

if (pid = fork() ) {

int status;

printf("I'm the parent!\n");

wait(&status);

} else {

printf("I'm the child!\n");

execve(“/bin/ls”, argv, envp);

}

Page 102: Embedded Linux Course Slides

102© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Linux Processes Stack

Linux process stack is auto expanding.

A default stack (8Mb) is allocated at process creation.

By default, use of additional stack will automatically trigger allocation of more stack space.

This behavior can be limited by setting a resource limit on the stack size.

More on that ahead.

Before going into real time critical sections of your code make sure stack is allocated!

Page 103: Embedded Linux Course Slides

103© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

POSIX Priorities

int sched_setscheduler(pid_t pid, int policy, const struct sched_param *p);

struct sched_param {

...

int sched_priority

};

sched_setscheduler sets both the scheduling policy and the associated parameters for the process identified by pid. If pid equals zero, the scheduler of the calling process will be set. The interpretation of the parameter p depends on the selected policy. Currently, the following three scheduling policies are supported under Linux: SCHED_FIFO, SCHED_RR, and SCHED_OTHER;

There is also a sched_getscheduler().

Page 104: Embedded Linux Course Slides

104© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

POSIX Priorities (2)

SCHED_OTHER: Default Linux time-sharing scheduling

Priority 0 is reserved for it.

Fair, no starvation.

Use this for any non critical tasks.

SCHED_FIFO: First In-First Out scheduling

Priorities 1 – 99.

Preemtive.

SCHED_RR: Round Robin scheduling

Like SCHED_FIFO + time slice

Page 105: Embedded Linux Course Slides

105© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Locking Memory

int mlock(const void *addr, size_t len);

mlock disables paging for the memory in the range starting at addr with

length len bytes.

int mlockall(int flags);

mlockall disables paging for all pages mapped into the address space of the calling process.

MCL_CURRENT Lock all pages which are currently mapped into the address space of the process.

MCL_FUTURE Lock all pages which will become mapped into the address space of the process in the future. These could be for instance new pages required by a growing heap and stack as well as new memory mapped files or shared memory regions.

Must lock memory to guarantee real time responses!

Page 106: Embedded Linux Course Slides

106© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Resource Limits

#include <sys/time.h>

#include <sys/resource.h>

struct rlimit { rlim_t rlim_cur; /* Soft limit */rlim_t rlim_max; /* Hard limit */

};

int getrlimit(int resource, struct rlimit *rlim)

int setrlimit(int resource, const struct rlimit

*rlim);

These system calls can be used to get/set soft and hard limits to process resource usage.

Page 107: Embedded Linux Course Slides

107© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Resource Limits Continued

RLIMIT_AS - maximum virtual memory the process can claim.

Sends SIGSEGV after limit passed.

Effect automatic stack expansion

RLIMIT_CPU - Limits CPU time the process can consume.

After soft limits sends SIGXCPU every seocnd.

After hard limit sends SIGKILL.

RLIMIT_DATA - Limits data segment max size.

RLIMIT_STACK - Limits the maximum stack size.

After limit sends SIGKILL.

Must register an alternate stack to handle signal.

Page 108: Embedded Linux Course Slides

108© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Threads and Processes

Thread 1Thread

1Thread

2Thread

3Thread

4

Process 123 Process 124

FileDescriptors

MemorySignal

HandlersFile

DescriptorsMemory

SignalHandlers

Stack

State

SignalMask

Stack

State

SignalMask

Stack

State

SignalMask

Stack

State

SignalMask

Stack

State

SignalMask

LocalStorage

LocalStorage

LocalStorage

LocalStorage

LocalStorage

Page 109: Embedded Linux Course Slides

109© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

POSIX Threads

Linux uses the POSIX Threads threading mechanism.

Linux threads are Light Weight Process – each thread is a task scheduled by the kernel's scheduler.

Process creation time is roughly double then a thread creation.

But Linux process creation time is relatively low.

To use threads in your code:

#include <pthreads.h>

In your Makefile:

Add -lpthreads -lrt to LDFLAGS.

Page 110: Embedded Linux Course Slides

110© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Creating Threads

Function: pthread_create()

int pthread_create(pthread_t * thread, const pthread_attr_t * attr,

void * (*start_routine)(void *), void * arg);

The pthread_create() routine creates a new thread within a process. The new thread starts in the start routine start_routine which has a start argument arg. The new thread has attributes specified with attr, or default attributes if attr is NULL.

If the pthread_create() routine succeeds it will return 0 and put the new thread id into thread, otherwise an error number shall be returned indicating the error.

Page 111: Embedded Linux Course Slides

111© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Creating Thread Attributes

Function: pthread_attr_init()

int pthread_attr_init(pthread_attr_t *attr);

Setting attributes for threads is achieved by filling a thread attribute object attr of type pthread_attr_t, then passing it as second argument to pthread_create(3). Passing NULL is equivalent to passing a thread attribute object with all attributes set to their default values.

pthread_attr_init initializes the thread attribute object attr and fills it with default values for the attributes.

Each attribute attrname can be individually set using the function pthread_attr_set|attrname| and retrieved using the function pthread_attr_get|attrname|.

Page 112: Embedded Linux Course Slides

112© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Destroying Thread Attributes

Function: pthread_attr_destroy()

int pthread_attr_destroy(pthread_attr_t *attr);

pthread_attr_destroy destroys a thread attribute object, which must not be reused until it is reinitialized. pthread_attr_destroy does nothing in the LinuxThreads implementation.

Attribute objects are consulted only when creating a new thread. The same attribute object can be used for creating several threads. Modifying an attribute object after a call to pthread_create does not change the attributes of the thread previously created.

Page 113: Embedded Linux Course Slides

113© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Detach State

Thread Attribute: detachstate

Control whether the thread is created in the joinable state or in the detached state. The default is joinable state.

In the joinable state, another thread can synchronize on the thread termination and recover its termination code using pthread_join(3), but some of the thread resources are kept allocated after the thread terminates, and reclaimed only when another thread performs pthread_join(3) on that thread.

In the detached state, the thread resources are immediately freed when it terminates, but pthread_join(3) cannot be used to synchronize on the thread termination.

A thread created in the joinable state can later be put in the detached thread using pthread_detach(3).

Page 114: Embedded Linux Course Slides

114© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Sched Policy

Thread Attribute: schedpolicy

Select the scheduling policy for the thread: one of SCHED_OTHER (regular, non-realtime scheduling), SCHED_RR (realtime, round-robin) or SCHED_FIFO (realtime, first-in first-out).

Default value: SCHED_OTHER.

The realtime scheduling policies SCHED_RR and SCHED_FIFO are available only to processes with superuser privileges.

The scheduling policy of a thread can be changed after creation with pthread_setschedparam(3).

Page 115: Embedded Linux Course Slides

115© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Sched Param

Thread Attribute: schedparam

Contain the scheduling parameters (essentially, the scheduling priority) for the thread.

Default value: priority is 0.

This attribute is not significant if the scheduling policy is SCHED_OTHER; it only matters for the realtime policies SCHED_RR and SCHED_FIFO.

The scheduling priority of a thread can be changed after creation with pthread_setschedparam(3).

Page 116: Embedded Linux Course Slides

116© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Inherit Sched

Thread Attribute: inheritsched

Indicate whether the scheduling policy and scheduling parameters for the newly created thread are determined by the values of the schedpolicy and schedparam attributes (PTHREAD_EXPLICIT_SCHED) or are inherited from the parent thread (value PTHREAD_INHERIT_SCHED).

Default value: PTHREAD_EXPLICIT_SCHED.

Page 117: Embedded Linux Course Slides

117© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Destroying ThreadsFunction: pthread_exit()

void pthread_exit(void * status);

The pthread_exit() routine terminates the currently running thread and makes status available to the thread that successfully joins, pthread_join(), with the terminating thread. In addition pthread_exit() executes any remaining cleanup handlers in the reverse order they were pushed, pthread_cleanup_push(), after which all appropriate thread specific destructors are called.

An implicit call to pthread_exit() is made if any thread, other than the thread in which main() was first called, returns from the start routine specified in pthread_create().

Page 118: Embedded Linux Course Slides

118© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Waiting for a thread to finishFunction: pthread_join()

int pthread_join(pthread_t thread, void ** status);

If the target thread thread is not detached and there are no other threads joined with the specified thread then the pthread_join() function suspends execution of the current thread and waits for the target thread thread to terminate. Otherwise the results are undefined.

On a successful call pthread_join() will return 0, and if status is non NULL then status will point to the status argument of pthread_exit(). On failure pthread_join() will return an error number indicating the error.

Also exists pthread_tryjoin_np() and pthread_timedjoin_np().

Page 119: Embedded Linux Course Slides

119© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Canceling Threads

Function: pthread_cancel()

int pthread_cancel(pthread_t thread);

Cancellation is the mechanism by which a thread can terminate the execution of another thread. More precisely, a thread can send a cancellation request to another thread. Depending on its settings, the target thread can then either ignore the request, honor it immediately, or defer it till it reaches a cancellation point.

When a thread eventually honors a cancellation request, it performs as if pthread_exit(PTHREAD_CANCELED) has been called at that point.

pthread_cancel sends a cancellation request to the thread denoted by the thread argument.

Page 120: Embedded Linux Course Slides

120© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Cancel State

Function: pthread_setcancelstate()

int pthread_setcancelstate(int state, int *oldstate);

pthread_setcancelstate changes the cancellation state for the calling thread -- that is, whether cancellation requests are ignored or not.

The state argument is the new cancellation state: either PTHREAD_CANCEL_ENABLE to enable cancellation, or PTHREAD_CANCEL_DISABLE to disable cancellation (cancellation requests are ignored).

If oldstate is not NULL, the previous cancellation state is stored in the location pointed to by oldstate, and can thus be restored later by another call to pthread_setcancelstate.

Page 121: Embedded Linux Course Slides

121© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Cancel Type

Function: pthread_setcanceltype()

int pthread_setcanceltype(int type, int *oldtype);

pthread_setcanceltype changes the type of responses to cancellation requests for the calling thread: asynchronous (immediate) or deferred.

The type argument is the new cancellation type: either PTHREAD_CANCEL_ASYNCHRONOUS to cancel the calling thread as soon as the cancellation request is received, or PTHREAD_CANCEL_DEFERRED to keep the cancellation request pending until the next cancellation point. If old type is not NULL, the previous cancellation state is stored in the location pointed to by oldtype, and can thus be restored later by another call to pthread_setcanceltype.

Page 122: Embedded Linux Course Slides

122© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Cancel Point Defaults

Threads are always created by pthread_create(3) with cancellation enabled and deferred. That is, the initial cancellation state is PTHREAD_CANCEL_ENABLE and the initial type is PTHREAD_CANCEL_DEFERRED.

Page 123: Embedded Linux Course Slides

123© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Cancel PointsCancellation points are those points in the program execution where a test for pending cancellation requests is performed and cancellation is executed if positive.

The following POSIX threads functions are cancellation points: pthread_join(3), pthread_cond_wait(3), pthread_cond_timedwait(3), pthread_testcancel(3), sem_wait(3), sigwait(3)

All other POSIX threads functions are guaranteed not to be cancellation points. That is, they never perform cancellation in deferred cancellation mode.

A number of system calls (basically, all system calls that may block, such as read(2), write(2), wait(2), etc.) and library functions that may call these system calls (e.g. fprintf(3)) are cancellation points.

Page 124: Embedded Linux Course Slides

124© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Test Cancel

Function: pthread_testcancell()

void pthread_testcancel(void);

pthread_testcancel does nothing except testing for pending cancellation and executing it. Its purpose is to introduce explicit checks for cancellation in long sequences of code that do not call cancellation point functions otherwise.

Page 125: Embedded Linux Course Slides

125© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Pthread Once

Function: pthread_once()

int pthread_once(pthread_once_t *once_control, void(*init_routine) (void));

The purpose of pthread_once is to ensure that a piece of initialization code is executed at most once. The once_control argument points to a static or extern variable statically initialized to PTHREAD_ONCE_INIT.

The first time pthread_once is called with a given once_control argument, it calls init_routine with no argument and changes the value of the once_control variable to record that initialization has been per formed. Subsequent calls to pthread_once with the same once_control argument do nothing

Page 126: Embedded Linux Course Slides

126© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Cleanup Handlers

Cleanup handlers are functions that get called when a thread terminates, either by calling pthread_exit(3) or because of cancellation.

Cleanup handlers are installed and removed following a stack-like discipline.

The purpose of cleanup handlers is to free the resources that a thread may hold at the time it terminates.

In particular, if a thread exits or is canceled while it owns a locked mutex, the mutex will remain locked forever and prevent other threads from executing normally. The best way to avoid this is, just before locking the mutex, to install a cleanup handler whose effect is to unlock the mutex.

Page 127: Embedded Linux Course Slides

127© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Cleanup Push

Function: pthread_cleanup_push()

void pthread_cleanup_push(void (*routine) (void *), void *arg);

pthread_cleanup_push installs the routine function with argument arg as a cleanup handler. From this point on to the matching pthread_cleanup_pop, the function routine will be called with arguments arg when the thread terminates, either through pthread_exit(3) or by cancellation.

If several cleanup handlers are active at that point, they are called in LIFO order: the most recently installed handler is called first.

Page 128: Embedded Linux Course Slides

128© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Cleanup Pop

Function: pthread_cleanup_pop()

void pthread_cleanup_pop(int execute);

pthread_cleanup_pop removes the most recently installed cleanup handler.

If the execute argument is not 0, it also executes the handler, by calling the routine function with arguments arg.

If the execute argument is 0, the handler is only removed but not executed.

Page 129: Embedded Linux Course Slides

129© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Cleanup Continued

Matching pairs of pthread_cleanup_push and pthread_cleanup_pop must occur in the same function, at the same level of block nesting and behave like brackets.

Here is how to lock a mutex mut in such a way that it will be unlocked if the thread is canceled while mut is locked:

pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut);

pthread_mutex_lock(&mut);

/* do some work */

pthread_cleanup_pop(1);

Page 130: Embedded Linux Course Slides

130© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Cleanup Extras

pthread_cleanup_push_defer_np is a non-portable extension that combines pthread_cleanup_push and pthread_setcanceltype(3). It pushes a cleanup handler just as pthread_cleanup_push does, but also saves the current cancellation type and sets it to deferred cancellation. This ensures that the cleanup mechanism is effective even if the thread was initially in asynchronous cancellation mode.

pthread_cleanup_pop_restore_np pops a cleanup handler introduced by pthread_cleanup_push_defer_np!, and restores the cancellation type to its value at the time pthread_cleanup_push_defer_np was called.

pthread_cleanup_push_defer_np and pthread_cleanup_pop_restore_np must occur in matching pairs, at the same level of block nesting.

Page 131: Embedded Linux Course Slides

131© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Barrier Init

Function: pthread_barrier_init()

int pthread_barrier_init(pthread_barrier_t *restrict barrier, const pthread_barrierattr_t *restrict attr, unsigned count);

The pthread_barrier_init() function shall allocate any resources required to use the barrier referenced by barrier and shall initialize the barrier with attributes referenced by attr.

The count argument specifies the number of threads that must call pthread_barrier_wait() before any of them successfully return from the call. The value specified by count must be greater than zero.

Page 132: Embedded Linux Course Slides

132© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Barrier Destroy

Function: pthread_barrier_destroy()

int pthread_barrier_destroy(pthread_barrier_t *barrier);

The pthread_barrier_destroy() function shall destroy the barrier referenced by barrier and release any resources used by the barrier.

The effect of subsequent use of the barrier is undefined until the barrier is reinitialized by another call to pthread_barrier_init().

The results are undefined if pthread_barrier_destroy() is called when any thread is blocked on the barrier, or if this function is called with an uninitialized barrier.

Page 133: Embedded Linux Course Slides

133© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Barrier Wait

Function: pthread_barrier_wait()

int pthread_barrier_wait(pthread_barrier_t *barrier);

The pthread_barrier_wait() function shall synchronize participating threads at the barrier referenced by barrier. The calling thread shall block until the required number of threads have called pthread_barrier_wait() specifying the barrier.

When the required number of threads have called pthread_barrier_wait() specifying the barrier, the constant PTHREAD_BARRIER_SERIAL_THREAD shall be returned to one unspecified thread and zero shall be returned to each of the remaining threads. At this point, the barrier shall be reset to the state it had as a result of the most recent pthread_barrier_init() function that referenced it.

Page 134: Embedded Linux Course Slides

134© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Linux IPC

POSIX IPC

SysV IPC

Pipes

Unix Domain Sockets

Signals

TCP/IP Sockets

Page 135: Embedded Linux Course Slides

135© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Creating a Mutex

Function: pthread_mutex_init()

int pthread_mutex_init(pthread_mutex_t * mutex, const pthread_mutex_attr *attr);

The pthread_mutex_init() routine creates a new mutex, with attributes specified with attr, or default attributes if attr is NULL.

If the pthread_mutex_init() routine succeeds it will return 0 and put the new mutex id into mutex, otherwise an error number shall be returned indicating the error.

Page 136: Embedded Linux Course Slides

136© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Destroying a Mutex

Function: pthread_mutex_destroy()

int pthread_mutex_destroy(pthread_mutex_t * mutex);

The pthread_mutex_destroy() routine destroys the mutex specified by mutex.

If the pthread_mutex_destroy() routine succeeds it will return 0, otherwise an error number shall be returned indicating the error.

Page 137: Embedded Linux Course Slides

137© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Locking MutexesFunction: pthread_mutex_lock()

int pthread_mutex_lock(pthread_mutex_t * mutex);

The pthread_mutex_lock() routine shall lock the mutex specified by mutex. If the mutex is already locked the calling thread blocks until the mutex becomes available.

If the pthread_mutex_lock() routine succeeds it will return 0, otherwise an error number shall be returned indicating the error.

Function: pthread_mutex_trylock()

int pthread_mutex_trylock(pthread_mutex_t * mutex);

The pthread_mutex_trylock() routine shall lock the mutex specified by mutex and return 0, otherwise an error number shall be returned indicating the error. In all cases the pthread_mutex_trylock() routine will not block the current running thread.

Page 138: Embedded Linux Course Slides

138© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Locking Mutexes

Function: pthread_mutex_timedlock()

int pthread_mutex_timedlock(pthread_mutex_t * mutex,struct timespec *restrict abs_timeout);

The pthread_mutex_timedlock() function shall lock the mutex object referenced by mutex. If the mutex is already locked, the calling thread shall block until the mutex becomes available as in the pthread_mutex_lock() function. If the mutex cannot be locked without waiting for another thread to unlock the mutex, this wait shall be terminated when the specified timeout expires.

The timeout shall expire when the absolute time specified by abs_timeout passes, as measured by the clock on which timeouts are based (that is, when the value of that clock equals or exceeds abs_timeout), or if the absolute time specified by abs_timeout has already been passed at the time of the call.

Page 139: Embedded Linux Course Slides

139© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Unlocking Mutexes

Function: pthread_mutex_unlock()

int pthread_mutex_unlock(pthread_mutex_t * mutex);

If the current thread is the owner of the mutex specifed by mutex, then the pthread_mutex_unlock() routine shall unlock the mutex. If there are any threads blocked waiting for the mutex, the the scheduler will determine which thread obtains the lock on the mutex, otherwise the mutex is available to the next thread that calls the routine pthread_mutex_lock(), or pthread_mutex_trylock().

If the pthread_mutex_unlock() routine succeeds it will return 0, otherwise an error number shall be returned indicating the error.

Page 140: Embedded Linux Course Slides

140© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Priority Inversion

99

50

31. Low Priority task takes mutex

3. Hi Priority task block on mutex

4. Medium Priority task preempts low priority task and high priority task

2. High Priority task preempts low priority task

Time

Task P

riori

ty

Page 141: Embedded Linux Course Slides

141© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Priority Inheritance and Ceilings

Priority inheritance and ceilings are methods to protect against priority inversions.

Linux only got support for them in 2.6.18-rc2, just a couple of weeks ago.

Patches to add support for older version exists.

Embedded Linux vendors usually provide patched kernels.

If the kernel version you're using is not patched, make sure to protect against this scenario in design

One possible way: raise the priority of each tasks trying to grab a mutex to the maximum priority of all possible contenders.

Page 142: Embedded Linux Course Slides

142© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

POSIX Condition Variables

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t

*mutex, const struct timespec *abstime);

int pthread_cond_signal(pthread_cond_t *cond);

int pthread_cond_broadcast(pthread_cond_t *cond);

The first two function calls are used for waiting on the condition var.

The latter two function calls are used to wake up waiting tasks:

pthread_cond_signal() call wakes up one single task that is waiting for the condition variable

pthread_cond_broadcast() call wakes up all waiting tasks.

Page 143: Embedded Linux Course Slides

143© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Condition Variable Usagevoid sem_wait(sem_t *sem) { pthread_mutex_lock(&sem->lock); while (sem->count == 0) pthread_cond_wait(&sem->cond, &sem->lock); sem->count++; pthread_mutex_unlock(&sem->lock);} void sem_post(sem_t *sem) { pthread_mutex_lock(&sem->lock); sem->count--; if (sem->count <= 0) pthread_cond_signal(&sem->cond); pthread_mutex_unlock(&sem->lock);}

The condition variable function calls are used within an area protected by the mutex that belong to the condition variable. The operating system releases the mutex every time it blocks a task on the condition variable; and it has locked the mutex again when it unblocks the calling task from the signaling call.

Page 144: Embedded Linux Course Slides

144© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

POSIX Semaphores

#include <semaphore.h>

int sem_init(sem_t *sem, int pshared, unsigned int value);

int sem_wait(sem_t * sem);

int sem_trywait(sem_t * sem);

int sem_post(sem_t * sem);

int sem_getvalue(sem_t * sem, int * sval);

int sem_destroy(sem_t * sem);

Page 145: Embedded Linux Course Slides

145© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Shared Memory using mmap

void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset);

The mmap function asks to map length bytes starting at offset offset from the file (or other object) specified by the file descriptor fd into memory, preferably at address start. This latter address is a hint only, and is usually specified as 0. The actual place where the object is mapped is returned by mmap, and is never 0.

The return value in case of an error is MAP_FAILED (-1) and NOT 0!

MAP_SHARED flag: Share this mapping with all other processes that map this bject. Storing to the region is equivalent to writing to the file. The file may not actually be updated until msync(2) or munmap(2) are called.

Page 146: Embedded Linux Course Slides

146© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

POSIX Shared Memory

void * shm_open(const char *name, int oflag, mode_t mode);

shm_open creates and opens a new, or opens an existing, POSIX shared memory object. A POSIX shared memory object is in effect a handle which can be used by unrelated processes to mmap(2) the same region of shared memory. The shm_unlink function performs the converse opera tion, removing an object previously created by shm_open.

The operation of shm_open is analogous to that of open(2). name specifies the shared memory object to be created or opened. For portable use, name should have an initial slash (/) and contain no embedded slashes.

Page 147: Embedded Linux Course Slides

147© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

SysV Mailboxes

key_t ftok(const char *pathname, int proj_id);

int msgget(key_t key, int msgflg);

int msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg);

ssize_t msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg);

Ftok generates a key from the pathname and project id.

Msgget creates a Mailbox from the key

Msgsnd sends a message and msgrcv retrieves it.

The different flags can control messages types (priorities), if receiving is a blocking or non blocking operations and mailbox permissions.

Page 148: Embedded Linux Course Slides

148© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

POSIX Pipes

int pipe(int filedes[2]);

pipe creates a pair of file descriptors, pointing to a pipe inode, and places them in the array pointed to by filedes. filedes[0] is forreading, filedes[1] is for writing.

FILE *popen(const char *command, const char *type);

The popen() function opens a process by creating a pipe, forking, and invoking the shell. Since a pipe is by definition unidirectional, the type argument may specify only reading or writing, not both; the resulting stream is correspondingly read-only or write-only.

A named version of pipes, called fifo also exists.

Page 149: Embedded Linux Course Slides

149© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

UNIX Domain Sockets

Files in the file system that acts like sockets.

All normal socket operations applies.

struct sockaddr_un server;

int sock;

sock = socket(AF_UNIX, SOCK_STREAM, 0);

server.sun_family = AF_UNIX;

strcpy(server.sun_path, SOCKET_NAME);

bind(sock, (struct sockaddr *) &server, sizeof(struct sockaddr_un));

UDS can be used to pass file descriptors between processes using a special socket option operation.

Page 150: Embedded Linux Course Slides

150© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Signalstypedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

int kill(pid_t pid, int sig);

The signal() system call installs a new signal handler for the signal with number signum. The signal handler is set to sighandler which may be a user specified function, or either SIG_IGN or SIG_DFL.

Upon arrival of a signal, if the corresponding handler is set to SIG_IGN, then the signal is ignored. If the handler is set to SIG_DFL, then the default action associated to the signal occurs.

Finally, if the handler is set to a function sighandler then first either the handler is reset to SIG_DFL or an implementation-dependent blocking of the signal is performed and next sighandler is called with argument signum.

Page 151: Embedded Linux Course Slides

151© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Regular Signals

� SIGHUP Hangup detected on controlling terminal� SIGINT Interrupt from keyboard� SIGQUIT Quit from keyboard� SIGILL Illegal Instruction� SIGABRT Abort signal from abort(3)� SIGFPE Floating point exception� SIGKILL Kill signal� SIGSEGV Invalid memory reference� SIGPIPE Broken pipe: write to pipe with no readers� SIGALRM Timer signal from alarm(2)� SIGTERM Termination signal� SIGUSR1 User-defined signal 1� SIGUSR2 User-defined signal 2� SIGCHLD Child stopped or terminate� SIGCONT Continue if stopped

SIGSTOP Stop processSIGTSTP Stop typed at ttySIGTTIN tty input for background processSIGTTOU tty output for background process

� SIGBUS Bus error (bad memory access)� SIGPOLL Pollable event (Sys V). Synonym of SIGIO� SIGPROF Profiling timer expired� SIGSYS Bad argument to routine (SVID)� SIGTRAP Trace/breakpoint trap� SIGURG Urgent condition on socket (4.2 BSD)� SIGIO I/O now possible (4.2 BSD)� SIGPWR Power failure (System V)� SIGWINCH Window resize signal (4.3 BSD, Sun)

Page 152: Embedded Linux Course Slides

152© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Problem with Regular Signals

Too few signals

Only 2 signals available for user defined uses: USR1, USR2

No queuing

If the same signal is sent multiple times until a task processes it, it is only delivered once.

No priority

Multiple signals delivered according to order sent.

Page 153: Embedded Linux Course Slides

153© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Real Time Signals

Additional 32 signals

From SIGRTMIN to SIGRTMAX

No predefined meaning

But LinuxThreads lib makes use of the first 3.

Multiple instances of the same signals are queued.

Value can be sent with the signal.

Priority is guaranteed: lowest number real time signals are delivered first. Same signals are delivered according to order they were sent.

Regular signals have higher priority then real time signals.

Page 154: Embedded Linux Course Slides

154© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Real Time Signals API

int sigaction(int signum, const struct sigaction *act, struct sigac-

tion *oldact);

Alternate way to register a signal handler.

Allow receiving an info struct with details

Allow sending a pointer with the signal

int sigqueue(pid_t pid, int sig, const union sigval value);

Alternate way to send signals

Allows sending real time signals that queue up

Page 155: Embedded Linux Course Slides

155© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Signals & Threads

Signal masks are per thread.

Signal handlers are per process.

Exception signals (SIGSEGV, SIGBUS) will be caught by thread doing the exception.

Other signals will be caught by any thread in the process whose masks does not block the signal.

Use a “signal handler” thread that does sigwait(3) to make thread catching less random.

Page 156: Embedded Linux Course Slides

156© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Processes Timers

#include <sys/time.h>

int getitimer(int which, struct itimerval *value);

int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);

The system provides each process with three interval timers, each decrementing in a distinct time domain.

When any timer expires, a signal is sent to the process, and the timer (potentially) restarts.

Page 157: Embedded Linux Course Slides

157© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Timers Expiry

The timer interval is controlled by the following structures:

struct itimerval {struct timeval it_interval; /* next value */struct timeval it_value; /* current value */

};

struct timeval {long tv_sec; /* seconds */long tv_usec; /* microseconds */

};

Timers decrement from it_value to zero, generate a signal, and reset to it_interval.

A timer which is set to zero (it_value is zero or the timer expires and it_interval is zero) stops.

Page 158: Embedded Linux Course Slides

158© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Time Domains

ITIMER_REAL

Decrements in real time, and delivers SIGALRM upon expiration.

ITIMER_VIRTUAL

Decrements only when the process is executing, and delivers SIGVTALRM upon expiration.

ITIMER_PROF

Decrements both when the process executes and when the system is executing on behalf of the process.

SIGPROF is delivered upon expiration.

Page 159: Embedded Linux Course Slides

159© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

More on Timers

Timers will never expire before the requested time, instead expiring some short, constant time afterwards, dependent on the system timer resolution.

If the timer expires while the process is active (always true for ITIMER_VIRT) the signal will be delivered immediately when generated.

Otherwise the delivery will be offset by a small time dependent on the system loading.

An alternate interface called timer_create() allows specifying which signal will be sent (utilize real time signals) and spawning of a thread on timer expiry.

Page 160: Embedded Linux Course Slides

160© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

The Unix and GNU / Linux command line

Going further

Page 161: Embedded Linux Course Slides

161© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Command help

Some Unix commands and most GNU / Linux commands offer at least one help argument:

-h(- is mostly used to introduce 1-character options)

--help(-- is always used to introduce the corresponding “long” option name, which makes scripts easier to understand)

You also often get a short summary of options when you input an invalid argument.

Page 162: Embedded Linux Course Slides

162© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Manual pages

man <keyword>Displays one or several manual pages for <keyword>

man man

Most available manual pages are about Unix commands, but some are also about C functions, headers or data structures, or even about system configuration files!

man stdio.h

man fstab (for /etc/fstab)

Manual page files are looked for in the directories specified by the MANPATH environment variable.

Page 163: Embedded Linux Course Slides

163© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Info pages

In GNU, man pages are being replaced by info pages. Some manual pages even tell to refer to info pages instead.

info <command>

info features:

Documentation structured in sections (“nodes”) and subsections (“subnodes”)

Possibility to navigate in this structure: top, next, prev, up

Info pages generated from the same texinfo source as the HTML documentation pages

Page 164: Embedded Linux Course Slides

164© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Kernel overviewLinux features

Page 165: Embedded Linux Course Slides

165© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Studied kernel version: 2.6

Linux 2.4

Mature

But developments stopped; very few developers willing to help.

Now obsolete and lacks recent features.

Still fine if you get your sources, tools and support from commercial Linux vendors.

Linux 2.6

2 years old stable Linux release!

Support from the Linux development community and all commercial vendors.

Now mature and more exhaustive. Most drivers upgraded.

Cutting edge features and increased performance.

Page 166: Embedded Linux Course Slides

166© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Linux kernel key features

Portability and hardware supportRuns on most architectures.

ScalabilityCan run on super computers as well as on tiny devices(4 MB of RAM is enough).

Compliance to standards and interoperability.

Exhaustive networking support.

SecurityIt can't hide its flaws. Its code is reviewed by many experts.

Stability and reliability.

ModularityCan include only what a system needs even at run time.

Easy to programYou can learn from existing code. Many useful resources on the net.

Page 167: Embedded Linux Course Slides

167© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Supported hardware architectures

See the arch/ directory in the kernel sources

Minimum: 32 bit processors, with or without MMU

32 bit architectures (arch/ subdirectories)alpha, arm, cris, frv, h8300, i386, m32r, m68k, m68knommu, mips, parisc, ppc, s390, sh, sparc, um, v850, xtensa

64 bit architectures:ia64, mips64, ppc64, sh64, sparc64, x86_64

See arch/<arch>/Kconfig, arch/<arch>/README, or Documentation/<arch>/ for details

Page 168: Embedded Linux Course Slides

168© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Kernel overviewKernel code

Page 169: Embedded Linux Course Slides

169© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Implemented in C

Implemented in C like all Unix systems.(C was created to implement the first Unix systems)

A little Assembly is used too:CPU and machine initialization, critical library routines.

See http://www.tux.org/lkml/#s15-3for reasons for not using C++(main reason: the kernel requires efficient code).

Page 170: Embedded Linux Course Slides

170© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Compiled with GNU C

Need GNU C extensions to compile the kernel.So, you cannot use any ANSI C compiler!

Some GNU C extensions used in the kernel:

Inline C functions

Inline assembly

Structure member initializationin any order (also in ANSI C99)

Branch annotation (see next page)

Page 171: Embedded Linux Course Slides

171© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Help gcc to optimize your code!

Use the likely and unlikely statements (include/linux/compiler.h)

Example:if (unlikely(err)) { ...}

The GNU C compiler will make your code fasterfor the most likely case.

Used in many places in kernel code!Don't forget to use these statements!

Page 172: Embedded Linux Course Slides

172© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

No C library

The kernel has to be standalone and can't use user-space code.Userspace is implemented on top of kernel services, not the opposite.Kernel code has to supply its own library implementations(string utilities, cryptography, uncompression ...)

So, you can't use standard C library functions in kernel code.(printf(), memset(), malloc()...).You can also use kernel C headers.

Fortunately, the kernel provides similar C functions for your convenience, like printk(), memset(), kmalloc() ...

Page 173: Embedded Linux Course Slides

173© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Kernel Stack

Very small and fixed stack.

2 page stack (8k), per task.

Or 1 page stack, per task and one for interrupts.

Chosen in build time via menu.

Not for all architectures

For some architectures, the kernel provides debug facility to detect stack overruns.

2.6

Page 174: Embedded Linux Course Slides

174© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Managing endianism

Linux supports both little and big endian architectures

Each architecture defines __BIG_ENDIAN or __LITTLE_ENDIAN in <asm/byteorder.h>Can be configured in some platforms supporting both.

To make your code portable, the kernel offers conversion macros (that do nothing when no conversion is needed). Most useful ones:u32 cpu_to_be32(u32); // CPU byte order to big endianu32 cpu_to_le32(u32); // CPU byte order to little endianu32 be32_to_cpu(u32); // Little endian to CPU byte orderu32 le32_to_cpu(u32); // Big endian to CPU byte order

Page 175: Embedded Linux Course Slides

175© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Kernel coding guidelines

Never use floating point numbers in kernel code. Your code may be run on a processor without a floating point unit (like on arm). Floating point can be emulated by the kernel, but this is very slow.

Define all symbols as static, except exported ones (avoid name space pollution)

All system calls return negative numebrs (error codes) for errors:

#include <linux/errno.h>

See Documentation/CodingStyle for more guidelines

Page 176: Embedded Linux Course Slides

176© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Kernel log

Printing to the kernel log is done via the printk function.

The kernel keeps the messages in a circular buffer(so that doesn't consume more memory with many messages)

Kernel log messages can be accessed from user space through system calls, or through /proc/kmsg

Kernel log messages are also displayed in the system console.

Page 177: Embedded Linux Course Slides

177© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

printk

The printk function:

Similar to stdlib's printf(3)

No floating point format.

Log message are prefixed with a “<1>”, where the number denotes severity, from 1 (most severe) to 8.

Macros are defined to be used for severity levels: KERN_EMERG, KERN_ALERT, KERT_CRIT, KERN_ERR, KERN_WARNING, KERN_NOTICE, KERN_INFO, KERN_DEBUG.

Usage example:

printk(KERN_DEBUG “Hello World number %d\n”, num);

Page 178: Embedded Linux Course Slides

178© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Accessing the kernel log

Watch the system console

syslogdDaemon gathering kernel messagesin /var/log/messagesFollow changes by running:tail -f /var/log/messagesCaution: this file grows!Use logrotate to control this

dmesgFound in all systemsDisplays the kernel log buffer

logreadSame. Often found in small embedded systems with no/var/log/messages or no dmesg. Implemented by Busybox.

cat /proc/kmsgWaits for kernel messages and displays them.Useful when none of the above user space programs are available (tiny system)

Many ways are available!

Page 179: Embedded Linux Course Slides

179© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Linked Lists

Many constructs use doubly-linked lists.

List definition and initialization:

struct list_head mylist = LIST_HEAD_INIT(mylist);

or

LIST_HEAD(mylist);

or

INIT_LIST_HEAD(&mylist);

Page 180: Embedded Linux Course Slides

180© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

List Manipulation

List definition and initialization:

void list_add(struct list_head *new, struct list_head *head);

void list_add_tail(struct list_head *new, struct list_head *head);

void list_del(struct list_head *entry);

void list_del_init(struct list_head *entry);

void list_move(struct list_head *list, struct list_head *head);

void list_add_tail(struct list_head *list, struct list_head *head);

Page 181: Embedded Linux Course Slides

181© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

List Manipulation (cont.)

List splicing and query:

void list_splice(struct list_head *list, struct list_head *head);

void list_add_splice_init(struct list_head *list, struct list_head *head);

void list_empty(struct list_head *head);

In 2.6, there are variants of these API's for RCU protected lists (see section about Locks ahead).

Page 182: Embedded Linux Course Slides

182© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

List Iteration

Lists also have iterator macros defined:

list_for_each(pos, head);

list_for_each_prev(pos, head);

list_for_each_safe(pos, n, head);

list_for_each_entry(pos, head, member);

Example:

struct mydata *pos;

list_for_each_entry(pos, head, dev_list) {

pos->some_data = 0777;

}

Page 183: Embedded Linux Course Slides

183© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Kernel overviewKernel subsystems

Page 184: Embedded Linux Course Slides

184© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Kernel architecture

Userspace

Kernelspace

Hardware

Page 185: Embedded Linux Course Slides

185© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Kernel Mode vs. User Mode

All modern CPUs support a dual mode of operation:

User mode, for regular tasks.

Supervisor (or privileged) mode, for the kernel.

The mode the CPU is in determines which instructions the CPU is willing to execute:

“Sensitive” instructions will not be executed when the CPU is in user mode.

The CPU mode is determined by one of the CPU registers, which stores the current “Ring Level”

0 for supervisor mode, 3 for user mode, 1-2 unused by Linux.

Page 186: Embedded Linux Course Slides

186© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

The System Call Interface

When a user space tasks needs to use a kernel service, it will make a “System Call”.

The C library places parameters and number of system call in registers and then issues a special trap instruction.

The trap atomically changes the ring level to supervisor mode and the sets the instruction pointer to the kernel.

The kernel will find the required system called via the system call table and execute it.

Returning from the system call does not require a special instruction, since in supervisor mode the ring level can be changed directly.

Page 187: Embedded Linux Course Slides

187© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Linux System Call Path

entry.S

Task

sys_name()

do_name()

Glibc

Function call

Trap

Kernel

Task

Page 188: Embedded Linux Course Slides

188© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Kernel memory constraints

Who can look after the kernel?

No memory protectionAccessing illegal memory locations result in (often fatal) kernel oopses.

Fixed size stack (8 or 4 KB)Unlike in userspace,no way to make it grow.

Kernel memory can't be swapped out (for the same reasons).

location Userspace memory managementUsed to implement:- memory protection- stack growth- memory swapping to disk

Page 189: Embedded Linux Course Slides

189© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Kernel overviewLinux versioning scheme and development process

Page 190: Embedded Linux Course Slides

190© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Linux Kernel Development Timeline

Page 191: Embedded Linux Course Slides

191© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Linux stable releases

Major versions

1 major version every 2 or 3 yearsExamples: 1.0, 2.0, 2.4, 2.6

Stable releases

1 stable release every 1 or 2 monthsExamples: 2.0.40, 2.2.26, 2.4.27, 2.6.7 ...

Stable release updates (since March 2005)

Updates to stable releases up to several times a weekAddress only critical issues in the latest stable releaseExamples: 2.6.11.1 to 2.6.11.7

Even number

Page 192: Embedded Linux Course Slides

192© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Linux development and testing releases

Testing releases

Several testing releases per month, before the next stable one.You can contribute to making kernel releases more stable by testing them!Example: 2.6.12-rc1

Development versions

Unstable versions used by kernel developersbefore making a new stable major releaseExamples: 2.3.42, 2.5.74

Odd number

Page 193: Embedded Linux Course Slides

193© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Continued development in Linux 2.6

Since 2.6.0, kernel developers have been able to introduce lots of new features one by one on a steady pace, without having to make major changes in existing subsystems.

Opening a new Linux 2.7 (or 2.9) development branch will be required only when Linux 2.6 is no longer able to accommodate key features without undergoing traumatic changes.

Thanks to this, more features are released to users at a faster pace.

However, the internal kernel API can undergo changes between two 2.6.x releases. A module compiled for a given version may no longer compile or work on a more recent one.

Page 194: Embedded Linux Course Slides

194© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Linux Kernel Development Process

Page 195: Embedded Linux Course Slides

195© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

What's new in each Linux release? (1)

The official list of changes for each Linux release is just a huge list of individual patches!

Very difficult to find out the key changes and to get the global picture out of individual changes.

commit 3c92c2ba33cd7d666c5f83cc32aa590e794e91b0Author: Andi Kleen <[email protected]>Date: Tue Oct 11 01:28:33 2005 +0200

[PATCH] i386: Don't discard upper 32bits of HWCR on K8 Need to use long long, not long when RMWing a MSR. I think it's harmless right now, but still should be better fixed if AMD adds any bits in the upper 32bit of HWCR. Bug was introduced with the TLB flush filter fix for i386 Signed-off-by: Andi Kleen <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>...

Page 196: Embedded Linux Course Slides

196© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

What's new in each Linux release? (2)

Fortunately, a summary of key changeswith enough details is available on http://wiki.kernelnewbies.org/LinuxChanges

For each new kernel release, you can also get the changes in the kernel internal API:http://lwn.net/Articles/2.6-kernel-api/

What's next?Documentation/feature-removal-schedule.txtlists the features, subsystems and APIs that are planned for removal (announced 1 year in advance).

??!

Page 197: Embedded Linux Course Slides

197© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Kernel overviewKernel user interface

Page 198: Embedded Linux Course Slides

198© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Mounting virtual filesystems

Linux makes system and kernel information available in user-space through virtual filesystems (virtual files not existing on any real storage). No need to know kernel programming to access this!

Mounting /proc:mount -t proc none /proc

Mounting /sys:mount -t sysfs none /sys

Filesystem type Raw deviceor filesystem imageIn the case of virtual

filesystems, any string is fine

Mount point

Page 199: Embedded Linux Course Slides

199© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Kernel userspace interface

A few examples:

/proc/cpuinfo: processor information

/proc/meminfo: memory status

/proc/version: version and build information

/proc/cmdline: kernel command line

/proc/<pid>/environ: calling environment

/proc/<pid>/cmdline: process command line

... and many more! See by yourself!

Page 200: Embedded Linux Course Slides

200© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Userspace interface documentation

Lots of details about the /proc interface are available in Documentation/filesystems/proc.txt(almost 2000 lines) in the kernel sources.

You can also find other details in the proc manual page:man proc

See the New Device Model section for details about /sys

Page 201: Embedded Linux Course Slides

201© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Compiling and booting LinuxGetting the sources

Page 202: Embedded Linux Course Slides

202© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Linux kernel size

Linux 2.6.16 sources:Raw size: 260 MB (20400 files, approx 7 million lines of code)bzip2 compressed tar archive: 39 MB (best choice)gzip compressed tar archive: 49 MB

Minimum compiled Linux kernel size (with Linux-Tiny patches)approx 300 KB (compressed), 800 KB (raw)

Why are these sources so big?Because they include thousands of device drivers, many network protocols, support many architectures and filesystems...

The Linux core (scheduler, memory management...) is pretty small!

Page 203: Embedded Linux Course Slides

203© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

kernel.org

Page 204: Embedded Linux Course Slides

204© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Getting Linux sources: 2 possibilities

Full sources

The easiest way, but longer to download.

Example:http://kernel.org/pub/linux/kernel/v2.6/linux-2.6.14.1.tar.bz2

Or patch against the previous version

Assuming you already have the full sources of the previous version

Example:http://kernel.org/pub/linux/kernel/v2.6/patch-2.6.14.bz2 (2.6.13 to 2.6.14)http://kernel.org/pub/linux/kernel/v2.6/patch-2.6.14.7.bz2 (2.6.14 to 2.6.14.7)

Page 205: Embedded Linux Course Slides

205© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Downloading full kernel sources

Downloading from the command line

With a web browser, identify the version you need on http://kernel.org

In the right directory, download the source archive and its signature(copying the download address from the browser):

wget http://kernel.org/pub/linux/kernel/v2.6/linux-2.6.11.12.tar.bz2wget http://kernel.org/pub/linux/kernel/v2.6/linux-2.6.11.12.tar.bz2.sign

Check the electronic signature of the archive:

gpg --verify linux-2.6.11.12.tar.bz2.sign

Extract the contents of the source archive:

tar jxvf linux-2.6.11.12.tar.bz2

~/.wgetrc config file for proxies:

http_proxy = <proxy>:<port>ftp_proxy = <proxy>:<port>proxy_user = <user> (if any)proxy_password = <passwd> (if any)

Page 206: Embedded Linux Course Slides

206© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Downloading kernel source patches (1)

Assuming you already have the linux-x.y.<n-1> version

Identify the patches you need on http://kernel.org with a web browser

Download the patch files and their signature:

Patch from 2.6.10 to 2.6.11wget ftp://ftp.kernel.org/pub/linux/kernel/v2.6/patch-2.6.11.bz2wget ftp://ftp.kernel.org/pub/linux/kernel/v2.6/patch-2.6.11.bz2.sign

Patch from 2.6.11 to 2.6.11.12 (latest stable fixes)wget http://www.kernel.org/pub/linux/kernel/v2.6/patch-2.6.11.12.bz2wget http://www.kernel.org/pub/linux/kernel/v2.6/patch-2.6.11.12.bz2.sign

Page 207: Embedded Linux Course Slides

207© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Downloading kernel source patches (2)

Check the signature of patch files:

gpg --verify patch-2.6.11.bz2.signgpg --verify patch-2.6.11.12.bz2.sign

Apply the patches in the right order:

cd linux-2.6.10/bzcat ../patch-2.6.11.bz2 | patch -p1 bzcat ../patch-2.6.11.12.bz2 | patch -p1cd ..mv linux-2.6.10 linux-2.6.11.12

Page 208: Embedded Linux Course Slides

208© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Checking the integrity of sources

Kernel source integrity can be checked through OpenPGP digital signatures.Full details on http://www.kernel.org/signature.html

If needed, read http://www.gnupg.org/gph/en/manual.html and create a new private and public keypair for yourself.

Import the public GnuPG key of kernel developers:

gpg --keyserver pgp.mit.edu --recv-keys 0x517D0F0E

If blocked by your firewall, look for 0x517D0F0E on http://pgp.mit.edu/, copy and paste the key to a linuxkey.txt file:gpg --import linuxkey.txt

Check the signature of files:gpg --verify linux-2.6.11.12.tar.bz2.sign

Page 209: Embedded Linux Course Slides

209© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Anatomy of a patch file

A patch file is the output of the diff command

diff -Nru a/Makefile b/Makefile--- a/Makefile 2005-03-04 09:27:15 -08:00+++ b/Makefile 2005-03-04 09:27:15 -08:00@@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 11-EXTRAVERSION =+EXTRAVERSION = .1 NAME=Woozy Numbat

# *DOCUMENTATION*

diff command line

File date info

Line numbers in files

Context info: 3 lines before the changeUseful to apply a patch when line numbers changed

Removed line(s) if anyAdded line(s) if any

Context info: 3 lines after the change

Page 210: Embedded Linux Course Slides

210© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Using the patch command

The patch command applies changes to files in the current directory:

Making changes to existing files

zcat diff_file.gz | patch -p<n>

n: number of directory levels to skip in the file paths

Page 211: Embedded Linux Course Slides

211© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Applying a Linux patch

Linux patches...

Always to apply to the x.y.<z-1> version

Always produced for n=1 (that's what everybody does... do it too!)

Downloadable in gzip and bzip2 (much smaller) compressed files.

Linux patch command line example:cd linux-2.6.10bzcat ../patch-2.6.11.bz2 | patch -p1cd ..; mv linux-2.6.10 linux-2.6.11

Keep patch files compressed: useful to check their signature later.You can still view (or even edit) the uncompressed data with vi:vi patch-2.6.11.bz2 (on the fly (un)compression)

Page 212: Embedded Linux Course Slides

212© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Accessing development sources (1)

Kernel development sources are now managed with git

You can browse Linus' git tree (if you just need to check a few files):http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=tree

Get and compile git from http://kernel.org/pub/software/scm/git/

Get and compile the cogito front-end fromhttp://kernel.org/pub/software/scm/cogito/

If you are behind a proxy, set Unix environment variables defining proxy settings. Example:export http_proxy="proxy.server.com:8080"export ftp_proxy="proxy.server.com:8080"

Page 213: Embedded Linux Course Slides

213© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Accessing development sources (2)

Pick up a git development tree on http://kernel.org/git/

Get a local copy (“clone”) of this tree.Example (Linus tree, the one used for Linux stable releases):

cg-clone http://kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.gitor cg-clone rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git

Update your copy whenever needed (Linus tree example):cd linux-2.6cg-update origin

More details availableon http://git.or.cz/ or http://linux.yyz.us/git-howto.html

Page 214: Embedded Linux Course Slides

214© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Compiling and booting LinuxStructure of source files

Page 215: Embedded Linux Course Slides

215© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Linux sources structure (1)

arch/<arch> Architecture specific codearch/<arch>/mach-<mach> Machine / board specific codeCOPYING Linux copying conditions (GNU GPL)CREDITS Linux main contributorscrypto/ Cryptographic librariesDocumentation/ Kernel documentation. Don't miss it!drivers/ All device drivers (drivers/usb/, etc.)fs/ Filesystems (fs/ext3/, etc.)include/ Kernel headersinclude/asm-<arch> Architecture and machine dependent headersinclude/linux Linux kernel core headersinit/ Linux initialization (including main.c)ipc/ Code used for process communication

Page 216: Embedded Linux Course Slides

216© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Linux sources structure (2)

kernel/ Linux kernel core (very small!)lib/ Misc library routines (zlib, crc32...)MAINTAINERS Maintainers of each kernel part. Very useful!Makefile Top Linux makefile (sets arch and version)mm/ Memory management code (small too!)net/ Network support code (not drivers)README Overview and building instructionsREPORTING-BUGS Bug report instructionsscripts/ Scripts for internal or external usesecurity/ Security model implementations (SELinux...)sound/ Sound support code and driversusr/ Early user-space code (initramfs)

Page 217: Embedded Linux Course Slides

217© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

On-line kernel documentation

http://free-electrons.com/kerneldoc/

Provided for all recent kernel releases

Easier than downloading kernel sources to access documentation

Indexed by Internet search enginesMakes kernel pieces of documentation easier to find!

Unlike most other sites offering this service too, also includes an HTML translation of kernel documents in the DocBook format.

Never forget documentation in the kernel sources! It's a very valuable way of getting information about the kernel.

Page 218: Embedded Linux Course Slides

218© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Compiling and booting LinuxKernel source management tools

Page 219: Embedded Linux Course Slides

219© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

LXR: Linux Cross Reference

http://sourceforge.net/projects/lxr

Generic source indexing tool and code browser

Web server basedVery easy and fast to use

Identifier or text search available

Very easy to find the declaration, implementation or usages of symbols

Supports C and C++

Supports huge code projects such as the Linux kernel (260 M in Apr. 2006)

Takes a little bit of time and patience to setup (configuration, indexing, server configuration).

Initial indexing quite slow:Linux 2.6.11: 1h 40min on P4 M1.6 GHz, 2 MB cache

You don't need to set up LXR by yourself.Use our http://lxr.free-electrons.com server! Other servers available on the Internet:http://free-electrons.com/community/kernel/lxr/

Page 220: Embedded Linux Course Slides

220© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

LXR screenshot

Page 221: Embedded Linux Course Slides

221© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Compiling and booting LinuxKernel configuration

Page 222: Embedded Linux Course Slides

222© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Kernel configuration overview

Makefile editionSetting the version and target architecture if needed

Kernel configuration: defining what features to include in the kernel:

make [config|xconfig|gconfig|menuconfig|oldconfig]

Kernel configuration file (Makefile syntax) storedin the .config file at the root of the kernel sources

Distribution kernel config files usually released in /boot/

Page 223: Embedded Linux Course Slides

223© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Makefile changes

To identify your kernel image with others build from the same sources, use the EXTRAVERSION variable:

VERSION = 2PATCHLEVEL = 6SUBLEVEL = 15EXTRAVERSION = -acme1

uname -r will return:2.6.15-acme1

Page 224: Embedded Linux Course Slides

224© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

make xconfig

make xconfig

New Qt configuration interface for Linux 2.6.Much easier to use than in Linux 2.4!

Make sure you readhelp -> introduction: useful options!

File browser: easier to load configuration files

Page 225: Embedded Linux Course Slides

225© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

make xconfig screenshot

Page 226: Embedded Linux Course Slides

226© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Compiling statically or as a module

Compiled as a module (separate file)CONFIG_ISO9660_FS=m

Driver optionsCONFIG_JOLIET=yCONFIG_ZISOFS=y

Compiled statically in the kernelCONFIG_UDF_FS=y

Page 227: Embedded Linux Course Slides

227© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

make config / menuconfig / gconfig

make config

Asks you the questions 1 by 1. Extremely long!

make menuconfig

Same old text interface as in Linux 2.4.Useful when no graphics are available.Pretty convenient too!

make gconfig

New GTK based graphical configuration interface. Functionality similar to that of make xconfig.

Page 228: Embedded Linux Course Slides

228© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

make oldconfig

make oldconfig

Needed very often!

Useful to upgrade a .config file from an earlier kernel release

Issues warnings for obsolete symbols

Asks for values for new symbols

If you edit a .config file by hand, it's strongly recommended to run make oldconfig afterwards!

Page 229: Embedded Linux Course Slides

229© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

make allnoconfig

make allnoconfig

Only sets strongly recommended settings to y.

Sets all other settings to n.

Very useful in embedded systems to select only the minimum required set of features and drivers.

Much more convenient than unselecting hundreds of features one by one!

Page 230: Embedded Linux Course Slides

230© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

make help

make help

Lists all available make targets

Useful to get a reminder, or to look for new or advanced options!

Page 231: Embedded Linux Course Slides

231© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Compiling and booting LinuxCompiling the kernel

Page 232: Embedded Linux Course Slides

232© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Compiling and installing the kernel

Compiling step

make

Install steps (logged as root!)

make install

make modules_install

Page 233: Embedded Linux Course Slides

233© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Dependency management

When you modify a regular kernel source file, make only rebuilds what needs recompiling. That's what it is used for.

However, the Makefile is quite pessimistic about dependencies. When you make significant changes to the .config file, make often redoes much of the compile job!

Page 234: Embedded Linux Course Slides

234© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Compiling faster with ccache

http://ccache.samba.org/Compiler cache for C and C++, already shipped by some distributionsMuch faster when compiling the same file a second time!

Very useful when .config file change are frequent.

Use it by adding a ccache prefixto the CC and HOSTCC definitions in Makefile:CC = ccache $(CROSS_COMPILE)gccHOSTCC = ccache gcc

Performance benchmarks:-63%: with a Fedora Core 3 config file (many modules!)-82%: with an embedded Linux config file (much fewer modules!)

Page 235: Embedded Linux Course Slides

235© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Kernel compiling tips

View the full (gcc, ld...) command line:make V=1

Clean-up generated files(to force re-compiling drivers):make clean

Remove all generated files(mainly to create patches)Caution: also removes your .config file!make mrproper

Page 236: Embedded Linux Course Slides

236© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Generated files

Created when you run the make command

vmlinuxRaw Linux kernel image, non compressed.

arch/<arch>/boot/zImage (default image on arm)zlib compressed kernel image

arch/<arch>/boot/bzImage (default image on i386)Also a zlib compressed kernel image.Caution: bz means “big zipped” but not “bzip2 compressed”!(bzip2 compression support only available on i386 as a tactical patch. Not very attractive for small embedded systems though: consumes 1 MB of RAM for decompression).

Page 237: Embedded Linux Course Slides

237© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Files created by make install

/boot/vmlinuz-<version>Compressed kernel image. Same as the one in arch/<arch>/boot

/boot/System.map-<version>Stores kernel symbol addresses

/boot/initrd-<version>.img (when used by your distribution)Initial RAM disk, storing the modules you need to mount your root filesystem. make install runs mkinitrd for you!

/etc/grub.conf or /etc/lilo.confmake install updates your bootloader configuration files to support your new kernel! It reruns /sbin/lilo if LILO is your bootloader.

Not relevant for embedded systems.

Page 238: Embedded Linux Course Slides

238© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Files created by make modules_install (1)

/lib/modules/<version>/: Kernel modules + extras

build/Everything needed to build more modules for this kernel: Makefile,.config file, module symbol information (module.symVers), kernel headers (include/ and include/asm/)

kernel/Module .ko (Kernel Object) files, in the same directory structure as in the sources.

Page 239: Embedded Linux Course Slides

239© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Files created by make modules_install (2)

/lib/modules/<version>/ (continued)

modules.aliasModule aliases for module loading utilities. Example line:alias sound-service-?-0 snd_mixer_oss

modules.depModule dependencies (see the Loadable kernel modules section)

modules.symbolsTells which module a given symbol belongs to.

All the files in this directory are text files.Don't hesitate to have a look by yourself!

Page 240: Embedded Linux Course Slides

240© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Compiling the kernel in a nutshell

Edit version information in the Makefile file

make xconfigmakemake installmake modules_install

Page 241: Embedded Linux Course Slides

241© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Compiling and booting LinuxCross-compiling the kernel

Page 242: Embedded Linux Course Slides

242© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Makefile changes

Update the version as usual

You should change the default target platform.Example: ARM platform, cross-compiler command: arm-linux-gcc

ARCH ?= armCROSS_COMPILE ?= arm-linux-(The Makefile defines later CC = $(CROSS_COMPILE)gcc)

See comments in Makefile for details

Page 243: Embedded Linux Course Slides

243© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Configuring the kernel

make xconfig

Same as in native compiling.

Don't forget to set the right board / machine type!

Page 244: Embedded Linux Course Slides

244© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Ready-made config files

assabet_defconfig integrator_defconfig mainstone_defconfigbadge4_defconfig iq31244_defconfig mx1ads_defconfigbast_defconfig iq80321_defconfig neponset_defconfigcerfcube_defconfig iq80331_defconfig netwinder_defconfigclps7500_defconfig iq80332_defconfig omap_h2_1610_defconfigebsa110_defconfig ixdp2400_defconfig omnimeter_defconfigedb7211_defconfig ixdp2401_defconfig pleb_defconfigenp2611_defconfig ixdp2800_defconfig pxa255-idp_defconfigep80219_defconfig ixdp2801_defconfig rpc_defconfigepxa10db_defconfig ixp4xx_defconfig s3c2410_defconfigfootbridge_defconfig jornada720_defconfig shannon_defconfigfortunet_defconfig lart_defconfig shark_defconfigh3600_defconfig lpd7a400_defconfig simpad_defconfigh7201_defconfig lpd7a404_defconfig smdk2410_defconfigh7202_defconfig lubbock_defconfig versatile_defconfighackkit_defconfig lusl7200_defconfig

arch/arm/configs example

Page 245: Embedded Linux Course Slides

245© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Using ready-made config files

Default configuration files available for many boards / machines!Check if one exists in arch/<arch>/configs/ for your target.

Example: if you found an acme_defconfig file, you can run:make acme_defconfig

Using arch/<arch>/configs/ is a very good good way of releasing a default configuration file for a group of users or developers.

Page 246: Embedded Linux Course Slides

246© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Cross-compiling setup

Example

If you have an ARM cross-compiling toolchainin /usr/local/arm/3.3.2/

You just have to add it to your Unix search path:export PATH=/usr/local/arm/3.3.2/bin:$PATH

Choosing a toolchain

See the Documentation/Changes file in the sources for details about minimum tool versions requirements.

Page 247: Embedded Linux Course Slides

247© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Building the kernel

Runmake

Copyarch/<platform>/boot/zImageto the target storage

You can customize arch/<arch>/boot/install.sh so that make install does this automatically for you.

make INSTALL_MOD_PATH=<dir>/ modules_installand copy <dir>/ to /lib/modules/ on the target storage

Page 248: Embedded Linux Course Slides

248© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Cross-compiling summary

Edit Makefile: set ARCH, CROSS_COMPILE and EXTRA_VERSION

Get the default configuration for your machine:make <machine>_defconfig (if existing in arch/<arch>/configs)

Refine the configuration settings according to your requirements:make xconfig

Add the crosscompiler path to your PATH environment variable

Compile the kernel: make

Copy the kernel image from arch/<arch>/boot/ to the target

Copy modules to a directory which you replicate on the target:make INSTALL_MOD_PATH=<dir> modules_install

Page 249: Embedded Linux Course Slides

249© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Compiling and booting LinuxOverall system startup

Page 250: Embedded Linux Course Slides

250© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Linux 2.4 booting sequence

Bootloader- Executed by the hardware at a fixed location in ROM / Flash- Initializes support for the device where the kernel image is found (local storage, network,removable media)- Loads the kernel image in RAM- Executes the kernel image (with a specified command line)

Kernel- Uncompresses itself- Initializes the kernel core and statically compiled drivers (needed to access the root filesystem)- Mounts the root filesystem (specified by the init kernel parameter)- Executes the first userspace program

First userspace program- Configures userspace and starts up system services

Page 251: Embedded Linux Course Slides

251© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Linux 2.6 booting sequence

Bootloader- Executed by the hardware at a fixed location in ROM / Flash- Initializes support for the device where the images are found (local storage, network, removable media)- Loads the kernel image in RAM- Executes the kernel image (with a specified command line)

Kernel- Uncompresses itself- Initializes the kernel core and statically compiled drivers- Uncompresses the initramfs cpio archive included in the kernel file cache (no mounting, no filesystem).- If found in the initramfs, executes the first userspace program: /init

Userspace: /init script (what follows is just a typical scenario)- Runs userspace commands to configure the device (such as network setup, mounting /proc and /sys...) - Mounts a new root filesystem. Switch to it (switch_root)- Runs /sbin/init (or sometimes a new /linuxrc script)

Userspace: /sbin/init- Runs commands to configure the device (if not done yet in the initramfs)- Starts up system services (daemons, servers) and user programs

Page 252: Embedded Linux Course Slides

252© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Linux 2.6 booting sequence with initrd

Bootloader- Executed by the hardware at a fixed location in ROM / Flash- Initializes support for the device where the images are found (local storage, network, removable media)- Loads the kernel and init ramdisk (initrd) images in RAM- Executes the kernel image (with a specified command line)

Kernel- Uncompresses itself- Initializes statically compiled drivers- Uncompresses the initramfs cpio archive included in the kernel. Mounts it. No /init executable found.- So falls back to the old way of trying to locate and mount a root filesystem.- Mounts the root filesystem specified by the init kernel parameter (initrd in our case)- Executes the first userspace program: usually /linuxrc

Userspace: /linuxrc script in initrd (what follows is just a typical sequence)- Runs userspace commands to configure the device (such as network setup, mounting /proc and /sys...) - Loads kernel modules (drivers) stored in the initrd, needed to access the new root filesystem.- Mounts the new root filesystem. Switch to it (pivot_root)- Runs /sbin/init (or sometimes a new /linuxrc script)

Userspace: /sbin/init- Runs commands to configure the device (if not done yet in the initrd)- Starts up system services (daemons, servers) and user programs

Page 253: Embedded Linux Course Slides

253© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Linux 2.4 booting sequence drawbacks

Trying to mount the filesystem specifiedby the init kernel parameter is complex:

Need device and filesystem drivers to be loaded

Specifying the root filesystem requires ugly black magic device naming (such as /dev/ram0, /dev/hda1...), while / doesn't exist yet!

Can require a complex initialization to implement within the kernel. Examples: NFS (set up an IP address, connect to the server...), RAID (root filesystem on multiple physical drives)...

In a nutshell: too much complexity in kernel code!

Page 254: Embedded Linux Course Slides

254© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Extra init ramdisk drawbacks

Init ramdisks are implemented as standard block devices

Need a ramdisk and filesystem driver

Fixed in size: cannot easily grow in size.Any free space cannot be reused by anything else.

Needs to be created and modified like any block device:formatting, mounting, editing, unmounting.Root permissions needed.

Like in any block device, files are first read from the storage,and then copied to the file cache.Slow and duplication in RAM!!!

Page 255: Embedded Linux Course Slides

255© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Initramfs features and advantages (1)

Root file system built in in the kernel image(embedded as a compressed cpio archive)

Very easy to create (at kernel build time).No need for root permissions (for mount and mknod).

Compared to init ramdisks, just 1 file to handle.

Always present in the Linux 2.6 kernel (empty by default).

Just a plain compressed cpio archive.Neither needs a block nor a filesystem driver.

Page 256: Embedded Linux Course Slides

256© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Initramfs features and advantages (2)

ramfs: implemented in the file cache.No duplication in RAM, no filesystem layer to manage.Just uses the size of its files. Can grow if needed.

Loaded by the kernel earlier.More initialization code moved to user-space!

Simpler to mount complex filesystems from flexible userspace scripts rather than from rigid kernel code. More complexity moved out to user-space!

No more magic naming of the root device.pivot_root no longer needed.

Page 257: Embedded Linux Course Slides

257© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Initramfs features and advantages (3)

Possible to add non GPL files (firmware, proprietary drivers)in the filesystem. This is not linking, just file aggregation(not considered as a derived work by the GPL).

Possibility to remove these files when no longer needed.

Still possible to use ramdisks.

More technical details about initramfs:see Documentation/filesystems/ramfs-rootfs-initramfs.txtand Documentation/early-userspace/README in kernel sources.

See also http://www.linuxdevices.com/articles/AT4017834659.html for a nice overview of initramfs (by Rob Landley, new Busybox maintainer).

Page 258: Embedded Linux Course Slides

258© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

How to populate an initramfs

Using CONFIG_INITRAMFS_SOURCEin kernel configuration (General Setup section)

Either specify an existing cpio archive

Or specify a list of files or directoriesto be added to the archive.

Or specify a text specification file (see next page)

Can use a tiny C library: klibc(ftp://ftp.kernel.org/pub/linux/libs/klibc/)

Page 259: Embedded Linux Course Slides

259© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Initramfs specification file example

dir /dev 755 0 0nod /dev/console 644 0 0 c 5 1nod /dev/loop0 644 0 0 b 7 0dir /bin 755 1000 1000slink /bin/sh busybox 777 0 0file /bin/busybox initramfs/busybox 755 0 0dir /proc 755 0 0dir /sys 755 0 0dir /mnt 755 0 0file /init initramfs/init.sh 755 0 0

No need for root user access!user id group id

Page 260: Embedded Linux Course Slides

260© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

How to handle compressed cpio archives

Useful when you want to build the kernel with a ready-made cpio archive. Better let the kernel do this for you!

Extracting:gzip -dc initramfs.img | cpio -id

Creating:find <dir> -print -depth | cpio -ov | gzip -c > initramfs.img

Page 261: Embedded Linux Course Slides

261© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

How to create an initrd

In case you really need an initrd (why?).

mkdir /mnt/initrddd if=/dev/zero of=initrd.img bs=1k count=2048mkfs.ext2 -F initrd.imgmount -o loop initrd.img /mnt/initrd

Fill the ramdisk contents: busybox, modules, /linuxrc scriptMore details in the Free Software tools for embedded systems training!

umount /mnt/initrdgzip --best -c initrd.img > initrd

More details on Documentation/initrd.txt in the kernel sources! Also explains pivot rooting.

Page 262: Embedded Linux Course Slides

262© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Compiling and booting LinuxBootloaders

Page 263: Embedded Linux Course Slides

263© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

x86 bootloaders

LILO: LInux LOad. Original Linux bootloader. Still in use!http://freshmeat.net/projects/lilo/Supports: x86

GRUB: GRand Unified Bootloader from GNU. More powerful.http://www.gnu.org/software/grub/Supports: x86

SYSLINUX: Utilities for network and removable media booting http://syslinux.zytor.comSupports: x86

Page 264: Embedded Linux Course Slides

264© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Generic bootloaders

Das U-Boot: Universal Bootloader from Denk SoftwareThe most used on arm.http://u-boot.sourceforge.net/ Supports: arm, ppc, mips, x86

RedBoot: eCos based bootloader from Red-Hathttp://sources.redhat.com/redboot/Supports: x86, arm, ppc, mips, sh, m68k...

uMon: MicroMonitor general purpose, multi-OS bootloaderhttp://microcross.com/html/micromonitor.htmlSupports: ARM, ColdFire, SH2, 68K, MIPS, PowerPC, Xscale...

Page 265: Embedded Linux Course Slides

265© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Other bootloaders

LAB: Linux As Bootloader, from Handhelds.orghttp://handhelds.org/cgi-bin/cvsweb.cgi/linux/kernel26/lab/Idea: use a trimmed Linux kernel with only features needed in a bootloader (no scheduling, etc.). Reuses flash and filesystem access, LCD interface, without having to implement bootloader specific drivers.Supports: arm (still experimental)

And many more: lots of platforms have their own!

Page 266: Embedded Linux Course Slides

266© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Postprocessing kernel image for U-boot

The U-boot bootloader needs extra information to be added to the kernel and initrd image files.

mkimage postprocessing utility provided in U-boot sources

Kernel image postprocessing:make uImage

Page 267: Embedded Linux Course Slides

267© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Postprocessing initrd image for U-boot

mkimage-n initrd \ Name-A arm \ Architecture-O linux \ Operating System-T ramdisk \ Type-C gzip \ Compression-d rd-ext2.gz \ Input fileuInitrd Output file

Page 268: Embedded Linux Course Slides

268© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Compiling U-boot mkimage

If you don't have mkimage yet

Get the U-boot sources fromhttp://u-boot.sourceforge.net/

In the U-boot source directory:Find the name of the config file for your board in include/configs (for example: omap1710h3.h)make omap1710h3_config (.h replaced by _config)make (or make -k if you have minor failures)cp tools/mkimage /usr/local/bin/

Page 269: Embedded Linux Course Slides

269© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Compiling and booting LinuxKernel booting

Page 270: Embedded Linux Course Slides

270© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Kernel command line parameters

As most C programs, the Linux kernel accepts command line arguments

Kernel command line arguments are part of the bootloader configuration settings.

Useful to configure the kernel at boot time, without having to recompile it.

Useful to perform advanced kernel and driver initialization, without having to use complex user-space scripts.

Page 271: Embedded Linux Course Slides

271© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Kernel command line example

HP iPAQ h2200 PDA booting example:

root=/dev/ram0 \ Root filesystem (first ramdisk)rw \ Root filesystem mounting modeinit=/linuxrc \ First userspace programconsole=ttyS0,115200n8 \ Console (serial)console=tty0 \ Other console (framebuffer)ramdisk_size=8192 \ Misc parameters...cachepolicy=writethrough

Hundreds of command line parameters described on Documentation/kernel-parameters.txt

Page 272: Embedded Linux Course Slides

272© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Booting variants

XIP (Execute In Place)

The kernel image is directly executed from the storage

Can be faster and save RAMHowever, the kernel image can't be compressed

No initramfs / initrd

Directly mounting the final root filesystem(root kernel command line option)

No new root filesystem

Running the whole system from the initramfs

Page 273: Embedded Linux Course Slides

273© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Usefulness of rootfs on NFS

Once networking works, your root filesystem could be a directory on your GNU/Linux development host, exported by NFS (Network File System). This is very convenient for system development:

Makes it very easy to update files (driver modules in particular) on the root filesystem, without rebooting. Much faster than through the serial port.

Can have a big root filesystem even if you don't have support for internal or external storage yet.

The root filesystem can be huge. You can even build native compiler tools and build all the tools you need on the target itself (better to cross-compile though).

Page 274: Embedded Linux Course Slides

274© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

NFS boot setup (1)

On the PC (NFS server)

Add the below line to your /etc/exports file:/home/rootfs 192.168.0.202(rw,insecure,sync,no_wdelay,no_root_squash)

If not running yet, you may need to start portmap/etc/init.d/portmap start

Start or restart your NFS server: Fedora Core: /etc/init.d/nfs restartDebian (Knoppix, KernelKit): /etc/init.d/nfs-user-server restart

client address NFS server options

Page 275: Embedded Linux Course Slides

275© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

NFS boot setup (2)

On the target (NFS client)

Compile your kernel with CONFIG_NFS_FS=yand CONFIG_ROOT_NFS=y

Boot the kernel with the below command line options:root=/dev/nfs

virtual deviceip=192.168.1.111:192.168.1.110:192.168.1.100:255.255.255.0:at91:eth0

local IP address server IP address gateway netmask hostname devicenfsroot=192.168.1.110:/home/nfsroot

NFS server IP address Directory on the NFS server

Page 276: Embedded Linux Course Slides

276© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

First user-space program

Specified by the init kernel command line parameter

Executed at the end of booting by the kernel

Takes care of starting all other user-space programs(system services and user programs).

Gets the 1 process number (pid)Parent or ancestor of all user-space programsThe system won't let you kill it.

Only other user-space program called by the kernel:/sbin/hotplug

Page 277: Embedded Linux Course Slides

277© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

/linuxrc

1 of the 2 default init programs(if no init parameter is given to the kernel)

Traditionally used in initrds or in simple systems not using /sbin/init.

Is most of the time a shell script, based on a very lightweight shell: nash or busybox sh

This script can implement complex tasks: detecting drivers to load, setting up networking, mounting partitions, switching to a new root filesystem...

Page 278: Embedded Linux Course Slides

278© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

The init program

/sbin/init is the second default init program

Takes care of starting system services, and eventually the user interfaces (sshd, X server...)

Also takes care of stopping system services

Lightweight, partial implementation available through busybox

See the Init runlevels annex section for more details about starting and stopping system services with init.

However, simple startup scripts are often sufficientin embedded systems.

Page 279: Embedded Linux Course Slides

279© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Compiling and booting LinuxLinux device files

Page 280: Embedded Linux Course Slides

280© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Character device files

Accessed through a sequential flow of individual characters

Character devices can be identified by their c type (ls -l):

crw-rw---- 1 root uucp 4, 64 Feb 23 2004 /dev/ttyS0crw--w---- 1 jdoe tty 136, 1 Feb 23 2004 /dev/pts/1crw------- 1 root root 13, 32 Feb 23 2004 /dev/input/mouse0crw-rw-rw- 1 root root 1, 3 Feb 23 2004 /dev/null

Example devices: keyboards, mice, parallel port, IrDA, Bluetooth port, consoles, terminals, sound, video...

Page 281: Embedded Linux Course Slides

281© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Block device files

Accessed through data blocks of a given size. Blocks can be accessed in any order.

Block devices can be identified by their b type (ls -l):

brw-rw---- 1 root disk 3, 1 Feb 23 2004 hda1brw-rw---- 1 jdoe floppy 2, 0 Feb 23 2004 fd0brw-rw---- 1 root disk 7, 0 Feb 23 2004 loop0brw-rw---- 1 root disk 1, 1 Feb 23 2004 ram1brw------- 1 root root 8, 1 Feb 23 2004 sda1

Example devices: hard or floppy disks, ram disks, loop devices...

Page 282: Embedded Linux Course Slides

282© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Device major and minor numbers

As you could see in the previous examples,device files have 2 numbers associated to them:

First number: major number

Second number: minor number

Major and minor numbers are used by the kernel to bind a driver to the device file. Device file names don't matter to the kernel!

To find out which driver a device file corresponds to,or when the device name is too cryptic,see Documentation/devices.txt.

Page 283: Embedded Linux Course Slides

283© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Device file creation

Device files are not created when a driver is loaded.

They have to be created in advance:mknod /dev/<device> [c|b] <major> <minor>

Examples:mknod /dev/ttyS0 c 4 64mknod /dev/hda1 b 3 1

Page 284: Embedded Linux Course Slides

284© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Drivers without device files

They don't have any corresponding /dev entry you could read or write through a regular Unix command.

Network driversThey are represented by a network device such as ppp0, eth1, usbnet, irda0 (listed by ifconfig -a)

Other driversOften intermediate or lowlevel drivers just interfacing with other ones. Example: usbcore.

Page 285: Embedded Linux Course Slides

285© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Driver developmentLoadable kernel modules

Page 286: Embedded Linux Course Slides

286© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Loadable kernel modules (1)

Modules: add a given functionality to the kernel (drivers, filesystem support, and many others)

Can be loaded and unloaded at any time, only when their functionality is need. Once loaded, have full access to the whole kernel. No particular protection.

Useful to keep the kernel image size to the minimum (essential in GNU/Linux distributions for PCs).

Page 287: Embedded Linux Course Slides

287© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Loadable kernel modules (2)

Useful to support incompatible drivers (either load one or the other, but not both)

Useful to deliver binary-only drivers (bad idea) without having to rebuild the kernel.

Modules make it easy to develop drivers without rebooting: load, test, unload, rebuild, load...

Modules can also be compiled statically into the kernel.

Page 288: Embedded Linux Course Slides

288© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Module dependencies

Module dependencies stored in/lib/modules/<version>/modules.dep

They don't have to be described by the module writer.

They are automatically computed during kernel building from module exported symbols. module2 depends on module1 if module2 uses a symbol exported by module1.

You can update the modules.dep file by running (as root)depmod -a [<version>]

Page 289: Embedded Linux Course Slides

289© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

hello module

/* hello.c */#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>

static int __init hello_init(void){ printk(KERN_ALERT "Good morrow"); printk(KERN_ALERT "to this fair assembly.\n"); return 0;}

static void __exit hello_exit(void){ printk(KERN_ALERT "Alas, poor world, what treasure"); printk(KERN_ALERT "hast thou lost!\n");}

module_init(hello_init);module_exit(hello_exit);MODULE_LICENSE("GPL");MODULE_DESCRIPTION("Greeting module");MODULE_AUTHOR("William Shakespeare");

__init:removed after initialization(static kernel or module).

__exit: discarded whenmodule compiled staticallyinto the kernel.

Example available on http://free-electrons.com/doc/c/hello.c

Page 290: Embedded Linux Course Slides

290© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Module license usefulness

Used by kernel developers to identify issues coming from proprietary drivers, which they can't do anything about.

Useful for users to check that their system is 100% free

Useful for GNU/Linux distributors for their release policy checks.

Page 291: Embedded Linux Course Slides

291© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Possible module license strings

GPLGNU Public License v2 or later

GPL v2GNU Public License v2

GPL and additional rights

Dual BSD/GPLGNU Public License v2 or BSD license choice

Dual MPL/GPLGNU Public License v2 or Mozilla license choice

ProprietaryNon free products

Available license strings explained in include/linux/module.h

Page 292: Embedded Linux Course Slides

292© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Compiling a module

The below Makefile should be reusable for any Linux 2.6 module.

Just run make to build the hello.ko file

Caution: make sure there is a [Tab] character at the beginning of the $(MAKE) line (make syntax)

# Makefile for the hello module

obj-m := hello.oKDIR := /lib/modules/$(shell uname -r)/buildPWD := $(shell pwd)default:

$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules[Tab]!(no spaces)

Either- full kernel source directory (configured and compiled)- or just kernel headers directory (minimum needed )

Example available on http://free-electrons.com/doc/c/Makefile

Page 293: Embedded Linux Course Slides

293© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Using the module

Need to be logged as root

Load the module:insmod ./hello.ko

You will see the following in the kernel log:Good morrowto this fair assembly

Now remove the module:rmmod hello

You will see:Alas, poor world, what treasurehast thou lost!

Page 294: Embedded Linux Course Slides

294© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Module utilities (1)

modinfo <module_name>modinfo <module_path>.koGets information about a module: parameters, license, description. Very useful before deciding to load a module or not.

insmod <module_name>insmod <module_path>.koTries to load the given module, if needed by searching for its .ko file throughout the default locations (can be redefined by the MODPATH environment variable).

Page 295: Embedded Linux Course Slides

295© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Module utilities (2)

modprobe <module_name>Most common usage of modprobe: tries to load all the modules the given module depends on, and then this module. Lots of other options are available.

lsmodDisplays the list of loaded modulesCompare its output with the contents of /proc/modules!

Page 296: Embedded Linux Course Slides

296© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Module utilities (3)

rmmod <module_name>Tries to remove the given module

modprobe -r <module_name>Tries to remove the given module and all dependent modules(which are no longer needed after the module removal)

Page 297: Embedded Linux Course Slides

297© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Driver developmentModule parameters

Page 298: Embedded Linux Course Slides

298© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

hello module with parameters

/* hello_param.c */#include <linux/init.h>#include <linux/module.h>#include <linux/moduleparam.h>

MODULE_LICENSE("GPL");

/* A couple of parameters that can be passed in: how many times we say hello, and to whom */

static char *whom = "world";module_param(whom, charp, 0);

static int howmany = 1;module_param(howmany, int, 0);

static int __init hello_init(void){ int i; for (i = 0; i < howmany; i++) printk(KERN_ALERT "(%d) Hello, %s\n", i, whom); return 0;}

static void __exit hello_exit(void){ printk(KERN_ALERT "Goodbye, cruel %s\n", whom);}

module_init(hello_init);module_exit(hello_exit);

Thanks toJonathan Corbetfor the example!

Example available on http://free-electrons.com/doc/c/hello_param.c

Page 299: Embedded Linux Course Slides

299© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Passing module parameters

Through insmod or modprobe:

insmod ./hello_param.ko howmany=2 whom=universe

Through modprobeafter changing the /etc/modprobe.conf file:

options hello_param howmany=2 whom=universe

Through the kernel command line, when the module is built statically into the kernel:

options hello_param.howmany=2 hello_param.whom=universe

module namemodule parameter namemodule parameter value

Page 300: Embedded Linux Course Slides

300© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Declaring a module parameter

#include <linux/moduleparam.h>

module_param(name, /* name of an already defined variable */type, /* either byte, short, ushort, int, uint, long,

ulong, charp, bool or invbool (checked at compile time!) */

perm /* for /sys/module/<module_name>/<param> 0: no such module parameter value file */

);

Example

int irq=5;module_param(irq, int, S_IRUGO);

Page 301: Embedded Linux Course Slides

301© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Declaring a module parameter array

#include <linux/moduleparam.h>

module_param_array(name, /* name of an already defined array */type, /* same as in module_param */num, /* number of elements in the array, or NULL (no check?) */perm /* same as in module_param */

);

Example

static int base[MAX_DEVICES] = { 0x820, 0x840 };module_param_array(base, int, NULL, 0);

Page 302: Embedded Linux Course Slides

302© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux

Driver developmentUsing the proc file system interface

Page 303: Embedded Linux Course Slides

303© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

hello module with proc file

#include <linux/proc_fs.h>

#define MYNAME "driver/my_proc_file"

static struct proc_dir_entry *my_proc_dir = NULL;

int mymodule_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data) {

int len = 0; len += sprintf(page + len, "io=%d\n", io); len += sprintf(page + len, "irq=%d\n", irq); if (len <= off+count) *eof = 1; *start = page + off; len -= off; if (len > count) len = count; if (len < 0) len = 0; return len;}

int __init startup_mymodule(void) { my_proc_dir = create_proc_entry(MYNAME, 0, NULL); my_proc_dir->read_proc = mymodule_proc_read; return 0;}

void __exit shutdown_mymodule(void) { remove_proc_entry(MYNAME, NULL);}

The proc file name

The proc_dir _entry struct

Callback function

page is the buffer wewrite to

Setting *eof to 1 meansend of file.

start is set to a pointer to where we wrote

second parameters isfile permission, lastparameter is a handleof directory.Don't forget to checkfor NULL here!

Page 304: Embedded Linux Course Slides

304© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Some more proc details

You can also register a proc_write callback.

proc_dir_entry has a data field. The kernel does not use it, but whatever you set there will be returned to you as the last parameter of the callback.

The permissions (2nd) parameter of create_proc_entry is the same as the mode flags of the open(2) system call.

0 means use the system wide defaults.

The directory handle (3rd) parameter of create_proc_entry is an address of proc_dir_entry for a proc directory.

NULL means the proc root directory.

For large and complex files use the seq_file wrapper.

Page 305: Embedded Linux Course Slides

305© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Using a proc file

Once the module is loaded, you can access the registered proc file:

From the shell:

Read cat /proc/driver/my_proc_file

Write echo “123” > /proc/driver/my_proc_fileProgramatically, using open(2), read(2) write(2) and related functions.

You can't delete, move or rename a proc file.

Proc files usually don't have reported size.

Page 306: Embedded Linux Course Slides

306© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Driver developmentAdding sources to the kernel tree

Page 307: Embedded Linux Course Slides

307© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

New directory in kernel sources (1)

To add an acme_drivers/ directory to the kernel sources:

Move the acme_drivers/ directory to the appropriate location in kernel sources

Create an acme_drivers/Kconfig file

Create an acme_drivers/Makefile file based on the Kconfig variables

In the parent directory Kconfig file, addsource “acme_drivers/Kconfig”

Page 308: Embedded Linux Course Slides

308© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

New directory in kernel sources (2)

In the parent directory Makefile file, addobj-$(CONFIG_ACME) += acme_drivers/ (just 1 condition)orobj-y += acme_drivers/ (several conditions)

Run make xconfig and see your new options!

Run make and your new files are compiled!

See Documentation/kbuild/ for details

Page 309: Embedded Linux Course Slides

309© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

How to create Linux patches

Download the latest kernel sources

Make a copy of these sources:rsync -a linux-2.6.9-rc2/ linux-2.6.9-rc2-patch/

Thanks to Nicolas Rougier (Copyright 2003, http://webloria.loria.fr/~rougier/) for the Tux image

Page 310: Embedded Linux Course Slides

310© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Driver developmentMemory management

Page 311: Embedded Linux Course Slides

311© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Physical Memory

In ccNUMA1 machines:

The memory of each node is represented in pg_data_t

These memories are linked into pgdat_list

In uniform memory access systems:

There is just one pg_data_t named contig_page_data

If you don't know which of these is your machine, you're using a uniform memory access system :-)

1 ccNUMA: Cache Coherent Non Uniform Memory Access

Page 312: Embedded Linux Course Slides

312© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Memory Zones

Each pg_data_t is split to three zones

Each zone has different properties:

ZONE_DMA

DMA operations on address limited busses is possible

ZONE_NORMAL

Maps directly to linear addressing (<~1Gb on i386)

Always mapped to kernel space.

ZONE_HIMEM

Rest of memory.

Mapped into kernel space on demand.

Page 313: Embedded Linux Course Slides

313© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Physical and virtual memory

0x00000000

0xFFFFFFFFF

Physical address space

RAM 0

RAM 1

Flash

I/O memory 1

I/O memory 2

I/O memory 3

MMU

MemoryManagement

Unit

CPU

Virtual address spaces

0xFFFFFFFFF

0x00000000

Kernel

0xFFFFFFFFF

0x00000000

Process1

0xFFFFFFFFF

0x00000000

Process2

All the processes have their own virtual address space, and run as if they had access to the whole address space.

Page 314: Embedded Linux Course Slides

314© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

3:1 Virtual Memory Map

0x00000000

0xFFFFFFFFF

Physical address space

1st Gb

2nd Gb

I/O memory

Virtual address spaces

0x00000000

0xFFFFFFFFF

User Space

Zero Page

KernelLogical

Addresses

KernelVirtual Addresses

PAGE_OFFSET0xC0000000

VMALLOC_START

3rd Gb

1:1persistentmapping

Randomopportunistic

mappings

Page 315: Embedded Linux Course Slides

315© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Address Types

Physical address

Physical memory as seen from the CPU, with out MMU1 translation.

Bus address

Physical memory as seen from device bus.

May or may not be virtualized (via IOMMU, GART, etc).

Virtual address

Memory as seen from the CPU, with MMU1 translation.1 MMU: Memory Management Unit

Page 316: Embedded Linux Course Slides

316© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Address Translation Macros

bus_to_phys(address)

phys_to_bus(address)

phys_to_virt(address)

virt_to_phys(address)

bus_to_virt(address)

virt_to_bus(address)

...

Page 317: Embedded Linux Course Slides

317© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

The MMU

Task Virtual Physical Permission

12 0x8000 0x5340 RWX

12 0x8001 0x1000 RX

15 0x8000 0x3390 RX

CPU MemoryMMU

Page 318: Embedded Linux Course Slides

318© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

kmalloc and kfree

Basic allocators, kernel equivalents of glibc's malloc and free.

static inline void *kmalloc(size_t size, int flags);size: number of bytes to allocateflags: priority (see next page)

void kfree (const void *objp);

Example:data = kmalloc(sizeof(*data), GFP_KERNEL);...kfree(data);

Page 319: Embedded Linux Course Slides

319© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

kmalloc features

Quick (unless it's blocked waiting for memory to be freed).

Doesn't initialize the allocated area.You can use kcalloc or kzalloc to get zeroed memory.

The allocated area is contiguous in physical RAM.

Allocates by 2n sizes, and uses a few management bytes.So, don't ask for 1024 when you need 1000! You'd get 2048!

Caution: drivers shouldn't try to kmallocmore than 128 KB (upper limit in some architectures).

Page 320: Embedded Linux Course Slides

320© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Main kmalloc flags (1)

Defined in include/linux/gfp.h (GFP: get_free_pages)

GFP_KERNELStandard kernel memory allocation. May block. Fine for most needs.

GFP_ATOMICAllocated RAM from interrupt handlers or code not triggered by user processes. Never blocks.

GFP_USERAllocates memory for user processes. May block. Lowest priority.

Page 321: Embedded Linux Course Slides

321© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Main kmalloc flags (2)

__GFP_DMAAllocate in DMA zone

__GFP_REPEATAsk to try harder. May still block, but less likely.

__GFP_NOFAILMust not fail. Never gives up.Caution: use only when mandatory!

__GFP_NORETRYIf allocation fails, doesn't try to get free pages.

Example:GFP_KERNEL | __GFP_DMA

Extra flags (can be added with |)

Page 322: Embedded Linux Course Slides

322© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Slab caches

Also called lookaside caches

Slab: name of the standard Linux memory allocator

Slab caches: Objects that can hold any numberof memory areas of the same size.

Optimum use of available RAM and reduced fragmentation.

Mainly used in Linux core subsystems: filesystems (open files, inode and file caches...), networking... Live stats on /proc/slabinfo.

May be useful in device drivers too, though not used so often.Linux 2.6: used by USB and SCSI drivers.

Page 323: Embedded Linux Course Slides

323© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Slab cache API (1)

#include <linux/slab.h>

Creating a cache:cache = kmem_cache_create (

name, /* Name for /proc/slabinfo */size, /* Cache object size */flags, /* Options: alignment, DMA... */constructor, /* Optional, called after each allocation */destructor); /* Optional, called before each release */

Page 324: Embedded Linux Course Slides

324© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Slab cache API (2)

Allocating from the cache:object = kmem_cache_alloc (cache, flags);

Freing an object:kmem_cache_free (cache, object);

Destroying the whole cache:kmem_cache_destroy (cache);

More details and an example in the Linux Device Drivers book: http://lwn.net/images/pdf/LDD3/ch08.pdf

Page 325: Embedded Linux Course Slides

325© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Memory pools

Useful for memory allocations that cannot fail

Kind of lookaside cache trying to keep a minimum number of pre-allocated objects ahead of time.

Use with care: otherwise can result in a lot of unused memory that cannot be reclaimed! Use other solutions whenever possible.

Page 326: Embedded Linux Course Slides

326© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Memory pool API (1)

#include <linux/mempool.h>

Mempool creation:mempool = mempool_create (

min_nr,alloc_function,free_function,pool_data);

Page 327: Embedded Linux Course Slides

327© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Memory pool API (2)

Allocating objects:object = mempool_alloc (pool, flags);

Freeing objects:mempool_free (object, pool);

Resizing the pool:status = mempool_resize (

pool, new_min_nr, flags);

Destroying the pool (caution: free all objects first!):mempool_destroy (pool);

Page 328: Embedded Linux Course Slides

328© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Memory pool implementation

mempool_create

mempool_alloc

mempool_free

Call allocfunction min_nr

times

Success?Call allocfunction

Call freefunctionon object

Take anobject from

the pool

pool count< min_nr?

Add freedobject to pool New object

Yes

No

Yes

No

Page 329: Embedded Linux Course Slides

329© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Memory pools using slab caches

Idea: use slab cache functions to allocate and free objects.

The mempool_alloc_slab and mempool_free_slab functions supply a link with slab cache routines.

So, you will find many code examples looking like:cache = kmem_cache_create (...);pool = mempool_create (

min_nr,mempool_alloc_slab,mempool_free_slab,cache);

Page 330: Embedded Linux Course Slides

330© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Allocating by pages

More appropriate when you need big slices of RAM:

unsigned long get_zeroed_page(int flags);Returns a pointer to a free page and fills it up with zeros

unsigned long __get_free_page(int flags);Same, but doesn't initialize the contents

unsigned long __get_free_pages(int flags, unsigned long order);Returns a pointer on a memory zone of several contiguous pages in physical RAM.order: log

2(<number_of_pages>)

maximum: 8192 KB (MAX_ORDER=11 in linux/mmzone.h)

Page 331: Embedded Linux Course Slides

331© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Freeing pages

void free_page(unsigned long addr);

void free_pages(unsigned long addr, unsigned long order);Need to use the same order as in allocation.

Page 332: Embedded Linux Course Slides

332© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

The Buddy System

Kernel memory page allocation follows the �Buddy� System.

Free Page Frames are allocated in powers of 2:

If suitable page frame is found, allocate.

Else: seek higher order frame, allocate half, keep �buddy�

When freeing page frames, coalescing occurs.

Page 333: Embedded Linux Course Slides

333© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Buddy System 1

16 Mb

We need 8 Mb of memory, but don't find an exact match.

We do have a block of 16 Mb memory though.

Page 334: Embedded Linux Course Slides

334© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Buddy System 2

8 Mb 8 Mb

So we'll split the 16 Mb into two 8 Mb areas.

Page 335: Embedded Linux Course Slides

335© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Buddy System 3

8 Mb 8 Mb

We'll use 8 Mb and keep the rest as a free block of 8 Mb.

Page 336: Embedded Linux Course Slides

336© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Buddy System 4

8 Mb 8 Mb

When the allocated memory has been freed...

Page 337: Embedded Linux Course Slides

337© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Buddy System 5

16 Mb

We can once again combine the two blocks in a single 16 Mb free block.

Because of the order of 2 allocation, it's easy to spot our �buddy�.

Page 338: Embedded Linux Course Slides

338© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

vmalloc

vmalloc can be used to obtain contiguous memory zones in virtual address space (even if pages may not be contiguous in physical memory).

void *vmalloc(unsigned long size);

void vfree(void *addr);

Page 339: Embedded Linux Course Slides

339© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Memory utilities

void * memset(void * s, int c, size_t count);Fills a region of memory with the given value.

void * memcpy(void * dest, const void *src, size_t count);Copies one area of memory to another.Use memmove with overlapping areas.

Lots of functions equivalent to standard C library ones defined in include/linux/string.h

Page 340: Embedded Linux Course Slides

340© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Memory management - Summary

Small allocations

kmalloc, kzalloc(and kfree!)

slab caches

memory pools

Bigger allocations

__get_free_page[s], get_zeroed_page,free_page[s]

vmalloc, vfree

Libc like memory utilities

memset, memcopy, memmove...

Page 341: Embedded Linux Course Slides

341© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Driver developmentI/O memory and ports

Page 342: Embedded Linux Course Slides

342© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Requesting I/O ports

struct resource *request_region( unsigned long start, unsigned long len, char *name);

Tries to reserve the given region and returns NULL if unsuccessful. Example:

request_region(0x0170, 8, "ide1");

void release_region( unsigned long start, unsigned long len);

See include/linux/ioport.h and kernel/resource.c

/proc/ioports example

0000-001f : dma10020-0021 : pic10040-0043 : timer00050-0053 : timer10060-006f : keyboard0070-0077 : rtc0080-008f : dma page reg00a0-00a1 : pic200c0-00df : dma200f0-00ff : fpu0100-013f : pcmcia_socket00170-0177 : ide101f0-01f7 : ide00376-0376 : ide10378-037a : parport003c0-03df : vga+03f6-03f6 : ide003f8-03ff : serial0800-087f : 0000:00:1f.00800-0803 : PM1a_EVT_BLK0804-0805 : PM1a_CNT_BLK0808-080b : PM_TMR0820-0820 : PM2_CNT_BLK0828-082f : GPE0_BLK...

Page 343: Embedded Linux Course Slides

343© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Reading / writing on I/O ports

The implementation of the below functions and the exact unsigned type can vary from platform to platform!

bytesunsigned inb(unsigned port);void outb(unsigned char byte, unsigned port);

wordsunsigned inw(unsigned port);void outw(unsigned char byte, unsigned port);

"long" integersunsigned inl(unsigned port);void outl(unsigned char byte, unsigned port);

Page 344: Embedded Linux Course Slides

344© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Reading / writing strings on I/O ports

Often more efficient than the corresponding C loop, if the processor supports such operations!

byte stringsvoid insb(unsigned port, void *addr, unsigned long count);void outsb(unsigned port, void *addr, unsigned long count);

word stringsvoid insw(unsigned port, void *addr, unsigned long count);void outsw(unsigned port, void *addr, unsigned long count);

long stringsvoid inbsl(unsigned port, void *addr, unsigned long count);void outsl(unsigned port, void *addr, unsigned long count);

Page 345: Embedded Linux Course Slides

345© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Requesting I/O memory

Equivalent functions with the same interface

struct resource * request_mem_region( unsigned long start, unsigned long len, char *name);

void release_mem_region( unsigned long start, unsigned long len);

/proc/iomem example

00000000-0009efff : System RAM0009f000-0009ffff : reserved000a0000-000bffff : Video RAM area000c0000-000cffff : Video ROM000f0000-000fffff : System ROM00100000-3ffadfff : System RAM 00100000-0030afff : Kernel code 0030b000-003b4bff : Kernel data3ffae000-3fffffff : reserved40000000-400003ff : 0000:00:1f.140001000-40001fff : 0000:02:01.0 40001000-40001fff : yenta_socket40002000-40002fff : 0000:02:01.1 40002000-40002fff : yenta_socket40400000-407fffff : PCI CardBus #0340800000-40bfffff : PCI CardBus #0340c00000-40ffffff : PCI CardBus #0741000000-413fffff : PCI CardBus #07a0000000-a0000fff : pcmcia_socket0a0001000-a0001fff : pcmcia_socket1e0000000-e7ffffff : 0000:00:00.0e8000000-efffffff : PCI Bus #01 e8000000-efffffff : 0000:01:00.0...

Page 346: Embedded Linux Course Slides

346© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Choosing I/O ranges

I/O port and memory ranges can be passed as module parameters. An easy way to define those parameters is through /etc/modprobe.conf.

Modules can also try to find free ranges by themselves (making multiple calls to request_region or request_mem_region.

Page 347: Embedded Linux Course Slides

347© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Mapping I/O memory in virtual memory

To access I/O memory, drivers need to have a virtual address that the processor can handle.

The ioremap functions satisfy this need:

#include <asm/io.h>

void *ioremap(unsigned long phys_addr, unsigned long size);void iounmap(void *address);

Caution: check that ioremap doesn't return a NULL address!

Page 348: Embedded Linux Course Slides

348© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Differences with standard memory

Reads and writes on memory can be cached

The compiler may choose to write the value in a cpu register, and may never write it in main memory.

The compiler may decide to optimize or reorder read and write instructions.

Page 349: Embedded Linux Course Slides

349© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Avoiding I/O access issues

Caching on I/O ports or memory already disabled, either by the hardware or by Linux init code.

Memory barriers are supplied to avoid reordering

Hardware independent

#include <asm/kernel.h>void barrier(void);

Only impacts the behavior of thecompiler. Doesn't prevent reorderingin the processor!

Hardware dependent

#include <asm/system.h>void rmb(void);void wmb(void);void mb(void);Safe on all architectures!

Page 350: Embedded Linux Course Slides

350© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Accessing I/O memory

Directly reading from or writing to addresses returned by ioremap (“pointer dereferencing”) may not work on some architectures.

Use the below functions instead. They are always portable and safe:unsigned int ioread8(void *addr); (same for 16 and 32)void iowrite8(u8 value, void *addr); (same for 16 and 32)

To read or write a series of values:void ioread8_rep(void *addr, void *buf, unsigned long count);void iowrite8_rep(void *addr, const void *buf, unsigned long count);

Other useful functions:void memset_io(void *addr, u8 value, unsigned int count);void memcpy_fromio(void *dest, void *source, unsigned int count);void memcpy_toio(void *dest, void *source, unsigned int count);

Page 351: Embedded Linux Course Slides

351© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

/dev/mem

Used to provide user-space applications with direct access to physical addresses.

Actually only works with addresses that are non-RAM (I/O memory) or with addresses that have some special flag set in the kernel's data structures. Fortunately, doesn't provide access to any address in physical RAM!

Used by applications such as the X server to write directly to device memory.

Page 352: Embedded Linux Course Slides

352© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Driver developmentCharacter drivers

Page 353: Embedded Linux Course Slides

353© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Usefulness of character drivers

Except for storage device drivers, most drivers for devices with input and output flows are implemented as character drivers.

So, most drivers you will face will be character driversYou will regret if you sleep during this part!

Page 354: Embedded Linux Course Slides

354© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Creating a character driver

User-space needs

The name of a device file in /dev to interact with the device driver through regular file operations (open, read, write, close...)

The kernel needs

To know which driver is in charge of device files with a given major / minor number pair

For a given driver, to have handlers (“file operations”) to execute when user-space opens, reads, writes or closes the device file.

/dev/foo

major / minor

Readhandler

Writehandler

Device driver

read write

Readbuffer

Writestring

Cop

y to

use

r

Cop

y fr

om u

ser

User-space

Kernel space

Page 355: Embedded Linux Course Slides

355© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Declaring a character driver

Device number registration

Need to register one or more device numbers (major / minor pairs), depending on the number of devices managed by the driver.

Need to find free ones!

File operations registration

Need to register handler functions called when user space programs access the device files: open, read, write, ioctl, close...

Page 356: Embedded Linux Course Slides

356© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Information on registered devices

Registered devices are visible in /proc/devices:

Character devices: Block devices:1 mem 1 ramdisk4 /dev/vc/0 3 ide04 tty 8 sd4 ttyS 9 md5 /dev/tty 22 ide15 /dev/console 65 sd5 /dev/ptmx 66 sd6 lp 67 sd7 vcs 68 sd10 misc 69 sd13 input14 sound...

Can be used to find free major numbers

Majornumber

Registeredname

Page 357: Embedded Linux Course Slides

357© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

dev_t structure

Kernel data structure to represent a major / minor pair

Defined in <linux/kdev_t.h>Linux 2.6: 32 bit size (major: 12 bits, minor: 20 bits)

Macro to create the structure:MKDEV(int major, int minor);

Macro to extract the numbers:MAJOR(dev_t dev);MINOR(dev_t dev);

Page 358: Embedded Linux Course Slides

358© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Allocating fixed device numbers

#include <linux/fs.h>

int register_chrdev_region(dev_t from, /* Starting device number */unsigned count, /* Number of device numbers */const char *name); /* Registered name */

Returns 0 if the allocation was successful.

Example

if (register_chrdev_region(MKDEV(202, 128), acme_count, “acme”)) {

printk(KERN_ERR “Failed to allocate device number\n”);...

Page 359: Embedded Linux Course Slides

359© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Dynamic allocation of device numbers

Safer: have the kernel allocate free numbers for you!

#include <linux/fs.h>

int alloc_chrdev_region(dev_t *dev, /* Output: starting device number */unsigned baseminor, /* Starting minor number, usually 0 */unsigned count, /* Number of device numbers */const char *name); /* Registered name */

Returns 0 if the allocation was successful.

Example

if (alloc_chrdev_region(&acme_dev, 0, acme_count, “acme”)) {printk(KERN_ERR “Failed to allocate device number\n”);...

Page 360: Embedded Linux Course Slides

360© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Creating device files

Issue: you can no longer create /dev entries in advance!You have to create them on the fly after loading the driver according to the allocated major number.

Trick: the script loading the module can then use /proc/devices:

module=foo; name=foo; device=foorm -f /dev/$deviceinsmod $module.komajor=`awk "\\$2==\"$name\" {print \\$1}" /proc/devices`mknod /dev/$device c $major 0

Caution: back quotes!

Page 361: Embedded Linux Course Slides

361© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

file operations (1)

Before registering character devices, you have to define file_operations (called fops) for the device files.Here are the main ones:

int (*open) (struct inode *, /* Corresponds to the device file */struct file *); /* Corresponds to the open file descriptor */

Called when user-space opens the device file.

int (*release) (struct inode *,struct file *);

Called when user-space closes the file.

Page 362: Embedded Linux Course Slides

362© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

The file structure

Is created by the kernel during the open call. Represents open files. Pointers to this structure are usually called "fips".

mode_t f_mode;The file opening mode (FMODE_READ and/or FMODE_WRITE)

loff_t f_pos;Current offset in the file.

struct file_operations *f_op;Allows to change file operations for different open files!

struct dentry *f_dentryUseful to get access to the inode: filp->f_dentry->d_inode.

Page 363: Embedded Linux Course Slides

363© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

file operations (2)

ssize_t (*read) (struct file *, /* Open file descriptor */char *, /* User-space buffer to fill up */size_t, /* Size of the user-space buffer */loff_t *); /* Offset in the open file */

Called when user-space reads from the device file.

ssize_t (*write) (struct file *, /* Open file descriptor */const char *, /* User-space buffer to write to the device */size_t, /* Size of the user-space buffer */loff_t *); /* Offset in the open file */

Called when user-space writes to the device file.

Page 364: Embedded Linux Course Slides

364© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Exchanging data with user-space (1)

The user-space address may be swapped out to disk

The user-space address may be invalid(user space process trying to access unauthorized data)

Page 365: Embedded Linux Course Slides

365© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Exchanging data with user-space (2)

You must use dedicated functions such as the following ones in your read and write file operations code:

include <asm/uaccess.h>

unsigned long copy_to_user (void __user *to, const void *from, unsigned long n);

unsigned long copy_from_user (void *to, const void __user *from, unsigned long n);

Make sure that these functions return 0!Another return value would mean that they failed.

Page 366: Embedded Linux Course Slides

366© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

file operations (3)

int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);Can be used to send specific commands to the device, which are neither reading nor writing (e.g. formatting a disk, configuration changes).

int (*mmap) (struct file *, struct vm_area_struct);Asking for device memory to be mapped into the address space of a user process

struct module *owner;Used by the kernel to keep track of who's using this structure and count the number of users of the module.

Page 367: Embedded Linux Course Slides

367© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

static ssize_tacme_read(struct file *file, char __user *buf, size_t count, loff_t * ppos){ /* The hwdata address corresponds to a device I/O memory area */ /* of size hwdata_size, obtained with ioremap() */ int remaining_bytes;

/* Number of bytes left to read in the open file */ remaining_bytes = min(hwdata_size - (*ppos), count); if (remaining_bytes == 0) {

/* All read, returning 0 (End Of File) */ return 0;

}

if (copy_to_user(buf /* to */, *ppos+hwdata /* from */, remaining_bytes)) { return -EFAULT; } else {

/* Increase the position in the open file */ *ppos += remaining_bytes; return remaining_bytes; }}

read operation example

Read method Piece of code available onhttp://free-electrons.com/doc/c/acme_read.c

Page 368: Embedded Linux Course Slides

368© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

write operation example

static ssize_tacme_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos){ /* Assuming that hwdata corresponds to a physical address range */ /* of size hwdata_size, obtained with ioremap() */

/* Number of bytes not written yet in the device */ remaining_bytes = hwdata_size - (*ppos); if (count > remaining_bytes) {

/* Can't write beyond the end of the device */ return -EIO;

}

if (copy_from_user(*ppos+hwdata /* to */, buf /* from */, count)) { return -EFAULT; } else {

/* Increase the position in the open file */ *ppos += count; return count; }}

Write method Piece of code available onhttp://free-electrons.com/doc/c/acme_write.c

Page 369: Embedded Linux Course Slides

369© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

file operations definition example (3)

Defining a file_operations structure

include <linux/fs.h>

static struct file_operations acme_fops ={

.owner = THIS_MODULE,

.read = acme_read,

.write = acme_write,};

You just need to supply the functions you implemented! Defaults for other functions (such as open, release...)are fine if you do not implement anything special.

Page 370: Embedded Linux Course Slides

370© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Character device registration (1)

The kernel represents character drivers with a cdev structure

Declare this structure globally (within your module):#include <linux/cdev.h>static struct cdev *acme_cdev;

In the init function, allocate the structure and set its file operations:acme_cdev = cdev_alloc();acme_cdev->ops = &acme_fops;acme_cdev->owner = THIS_MODULE;

Page 371: Embedded Linux Course Slides

371© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Character device registration (2)

Then, now that your structure is ready, add it to the system:

int cdev_add(struct cdev *p, /* Character device structure */dev_t dev, /* Starting device major / minor number */unsigned count); /* Number of devices */

Example (continued):if (cdev_add(acme_cdev, acme_dev, acme_count)) {printk (KERN_ERR “Char driver registration failed\n”);...

Page 372: Embedded Linux Course Slides

372© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Character device unregistration

First delete your character device:void cdev_del(struct cdev *p);

Then, and only then, free the device number:void unregister_chrdev_region(dev_t from, unsigned count);

Example (continued):cdev_del(acme_cdev);unregister_chrdev_region(acme_dev, acme_count);

Page 373: Embedded Linux Course Slides

373© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Linux error codes

Try to report errors with error numbers as accurate as possible! Fortunately, macro names are explicit and you can remember them quickly.

Generic error codes:include/asm-generic/errno-base.h

Platform specific error codes:include/asm/errno.h

Page 374: Embedded Linux Course Slides

374© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Char driver example summary (1)

static void *acme_buf;static acme_bufsize=8192;

static int acme_count=1;static dev_t acme_dev;

static struct cdev *acme_cdev;

static ssize_t acme_write(...) {...}

static ssize_t acme_read(...) {...}

static struct file_operations acme_fops ={

.owner = THIS_MODULE,

.read = acme_read,

.write = acme_write,};

Page 375: Embedded Linux Course Slides

375© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Char driver example summary (2)

static int __init acme_init(void){ acme_buf = kmalloc(acme_bufsize, GFP_KERNEL);

if (!acme_buf) { err = -ENOMEM; goto err_exit; }

if (alloc_chrdev_region(&acme_dev, 0, acme_count, “acme”)) { err=-ENODEV; goto err_free_buf; }

acme_cdev = cdev_alloc();

if (!acme_cdev) { err=-ENOMEM; goto err_dev_unregister; }

acme_cdev->ops = &acme_fops; acme_cdev->owner = THIS_MODULE;

if (cdev_add(acme_cdev, acme_dev, acme_dev_count)) { err=-ENODEV; goto err_free_cdev; }

return 0;

err_free_cdev: kfree(acme_cdev);err_dev_unregister: unregister_chrdev_region( acme_dev, acme_count);err_free_buf: kfree(acme_buf);err_exit: return err;}

static void __exit acme_exit(void){cdev_del(acme_cdev);unregister_chrdev_region(acme_dev, acme_count);kfree(acme_buf);}

Show how to handle errors and deallocate resources in the right order!

Page 376: Embedded Linux Course Slides

376© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Character driver summary

Character driver writer- Define the file operations callbacks for the device file: read, write, ioctl...- In the module init function, get major and minor numbers with alloc_chrdev_region(),init a cdev structure with your file operations and add it to the system with cdev_add().- In the module exit function, call cdev_del() and unregister_chrdev_region()

System administration- Load the character driver module- In /proc/devices, find the major number it uses.- Create the device file with this major numberThe device file is ready to use!

System user- Open the device file, read, write, or send ioctl's to it.

Kernel- Executes the corresponding file operations

Ker

nel

Ker

nel

Use

r-sp

ace

Page 377: Embedded Linux Course Slides

377© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Driver developmentDebugging

Page 378: Embedded Linux Course Slides

378© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Usefulness of a serial port

Most processors feature a serial port interface (usually very well supported by Linux). Just need this interface to be connected to the outside.

Easy way of getting the first messages of an early kernel version, even before it boots. A minimum kernel with only serial port support is enough.

Once the kernel is fixed and has completed booting, possible to access a serial console and issue commands.

The serial port can also be used to transfer files to the target.

Page 379: Embedded Linux Course Slides

379© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

When you don't have a serial port

On the host

Not an issue. You can get a USB to serial converter. Usually very well supported on Linux and roughly costs $20. The device appears as /dev/ttyUSB0 on the host.

On the target

Check whether you have an IrDA port. It's usually a serial port too.

If you have an Ethernet adapter, try with it

You may also try to manually hook-up the processor serial interface (check the electrical specifications first!)

Page 380: Embedded Linux Course Slides

380© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Debugging with printk

Universal debugging technique used since the beginning of programming (first found in cavemen drawings)

Printed or not in the console or /var/log/messages according to the priority. This is controlled by the loglevel kernel parameter, or through /proc/sys/kernel/printk(see Documentation/sysctl/kernel.txt)

Available priorities (include/linux/kernel.h):

#define KERN_EMERG "<0>" /* system is unusable */#define KERN_ALERT "<1>" /* action must be taken immediately */#define KERN_CRIT "<2>" /* critical conditions */#define KERN_ERR "<3>" /* error conditions */#define KERN_WARNING "<4>" /* warning conditions */#define KERN_NOTICE "<5>" /* normal but significant condition */#define KERN_INFO "<6>" /* informational */#define KERN_DEBUG "<7>" /* debug-level messages */

Page 381: Embedded Linux Course Slides

381© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Debugging with /proc or /sys (1)

Instead of dumping messages in the kernel log, you can have your drivers make information available to user space

Through a file in /proc or /sys, which contents are handled by callbacks defined and registered by your driver.

Can be used to show any piece of informationabout your device or driver.

Can also be used to send data to the driver or to control it.

Caution: anybody can use these files.You should remove your debugging interface in production!

Page 382: Embedded Linux Course Slides

382© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Debugging with /proc or /sys (2)

Examples

cat /proc/acme/stats (dummy example)Displays statistics about your acme driver.

cat /proc/acme/globals (dummy example)Displays values of global variables used by your driver.

echo 600000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed

Adjusts the speed of the CPU (controlled by the cpufreq driver).

Page 383: Embedded Linux Course Slides

383© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Debugging with ioctl

Can use the ioctl() system call to query information about your driver (or device) or send commands to it.

This calls the ioctl file operation that you can register in your driver.

Advantage: your debugging interface is not public.You could even leave it when your system (or its driver) is in the hands of its users.

Page 384: Embedded Linux Course Slides

384© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Debugging with gdb

Schrödinger penguin principle.If you execute the kernel from a debugger on the same machine, this will interfere with the kernel behavior.

However, you can access the current kernel state with gdb:gdb /usr/src/linux/vmlinux /proc/kcore

uncompressed kernel kernel address space

You can access kernel structures, follow pointers... (read only!)

Requires the kernel to be compiled with CONFIG_DEBUG_INFO (Kernel hacking section)

Page 385: Embedded Linux Course Slides

385© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

kgdb kernel patch

http://kgdb.linsyssoft.com/

The execution of the patched kernel is fully controlled by gdb from another machine, connected through a serial line.

Can do almost everything, including inserting breakpoints in interrupt handlers.

Supported architectures: i386, x86_64, ppc and s390.

Page 386: Embedded Linux Course Slides

386© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Kernel crash analysis with kexec

kexec system call: makes it possible to call a new kernel, without rebooting and going through the BIOS / firmware.

Idea: after a kernel panic, make the kernel automatically execute a new, clean kernel from a reserved location in RAM, to perform post-mortem analysis of the memory of the crashed kernel.

See Documentation/kdump/kdump.txtin the kernel sources for details.

1. Copy debugkernel to reservedRAM

Standard kernel

2. kernel panic, kexec debug kernel

3. Analyze crashedkernel RAM

Regular RAM

Debug kernel

Page 387: Embedded Linux Course Slides

387© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Kernel Oops

Caused by an exception in the kernel code itself.

The kernel issues a diagnostic messaged, called an Oops!. The message contains debug information, such as register content, stack trace, code dump etc.

After the message is sent to the log and console -

From within a task – the kernel kills the task.

From interrupt – the kernel panics and may reboot automatically if given a-priori the panic=secs parameter.

In 2.4, stack trace addresses can be translated via the ksymoops utility. In 2.6, with the CONFIG_KALLSYMS option on, the kernel does translation internally.

Page 388: Embedded Linux Course Slides

388© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Kernel Oops Example

Unable to handle kernel NULL pointer dereference at virtual address 00000014

printing eip: d8d4d545*pde = 00000000Oops: 0000CPU: 0EIP: 0010:[<d8d4d545>] Tainted: PFEFLAGS: 00013286eax: c8b078c0 ebx: c8b078c0 ecx: 00000019 edx: c8b078c0esi: 00000000 edi: 00000000 ebp: bffff75c esp: c403bf84ds: 0018 es: 0018 ss: 0018Process vmware (pid: 5194, stackpage=c403b000)Stack: c8b078c0 00000000 bffff35c 00000000 c0136d64 c403bfa4 c8b078c0

c0130185Call Trace: [sys_stat64+100/112] [filp_close+53/112]

[sys_close+67/96] [system_call+51/56]

Code: f6 46 14 01 74 1c 83 c4 f4 8b 06 50 e8 da 62 43 e7 83 c4 f8

Page 389: Embedded Linux Course Slides

389© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Kernel debugging tips

If your kernel doesn't boot yet or hangs without any message, it can help to activate Low Level debugging(Kernel Hacking section, only available on arm):CONFIG_DEBUG_LL=y

More about kernel debugging in the free Linux Device Drivers book (References section)!

Page 390: Embedded Linux Course Slides

390© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Driver developmentConcurrent access to resources

Page 391: Embedded Linux Course Slides

391© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Sources of concurrency issues

The same resources can be accessed by several kernel processes in parallel, causing potential concurrency issues

Several user-space programs accessing the same device data or hardware. Several kernel processes could execute the same code on behalf of user processes running in parallel.

Multiprocessing: the same driver code can be running on another processor. This can also happen with single CPUs with hyperthreading.

Kernel preemption, interrupts: kernel code can be interrupted at any time (just a few exceptions), and the same data may be access by another process before the execution continues.

Page 392: Embedded Linux Course Slides

392© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Avoiding concurrency issues

Avoid using global variables and shared data whenever possible(cannot be done with hardware resources)

Don't make resources available to other kernel processes until they are ready to be used.

Use techniques to manage concurrent access to resources.

See Rusty Russell's Unreliable Guide To LockingDocumentation/DocBook/kernel-locking/in the kernel sources.

Page 393: Embedded Linux Course Slides

393© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Concurrency protection with semaphores

Page 394: Embedded Linux Course Slides

394© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Kernel semaphores

Also called “mutexes” (Mutual Exclusion)

1(free)

0(locked)

P(down)

V(up)

P: “Probeer”“Try” (to decrement) in Dutch

V: “Verhoog”“Increment” in Dutch

Page 395: Embedded Linux Course Slides

395© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Initializing a semaphore

StaticallyDECLARE_MUTEX(name);DECLARE_MUTEX_LOCKED(name);

Dynamicallyvoid init_MUTEX(struct semaphore *sem);void init_MUTEX_LOCKED(struct semaphore *sem);

Page 396: Embedded Linux Course Slides

396© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

locking and unlocking semaphores

void down (struct semaphore *sem);Decrements the semaphore if set to 1, waits otherwise.Caution: can't be interrupted, causing processes you cannot kill!

int down_interruptible (struct semaphore *sem);Same, but can be interrupted. If interrupted, returns a non zero value and doesn't hold the semaphore. Test the return value!!!

int down_trylock (struct semaphore *sem);Never waits. Returns a non zero value if the semaphore is not available.

void up (struct semaphore *sem);Releases the semaphore. Make sure you do it as soon as possible!

Page 397: Embedded Linux Course Slides

397© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Reader / writer semaphores

Allow shared access by unlimited readers, or by only 1 writer. Writers get priority.

void init_rwsem (struct rw_semaphore *sem);

void down_read (struct rw_semaphore *sem);int down_read_trylock (struct rw_semaphore *sem);int up_read (struct rw_semaphore *sem);

void down_write (struct rw_semaphore *sem);int down_write_trylock (struct rw_semaphore *sem);int up_write (struct rw_semaphore *sem);

Well suited for rare writes, holding the semaphore briefly. Otherwise, readers get starved, waiting too long for the semaphore to be released.

Page 398: Embedded Linux Course Slides

398© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

When to use semaphores

Before and after accessing shared resources

Before and after making other resources available to other parts of the kernel or to user-space (typically and module initialization).

In situations when sleeping is allowed.

Page 399: Embedded Linux Course Slides

399© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Spinlocks

Locks to be used for code that can't sleep (critical sections, interrupt handlers... Be very careful not to call functions which can sleep!

Intended for multiprocessor systems

Spinlocks are not interruptible,don't sleep and keep spinning in a loopuntil the lock is available.

Spinlocks cause kernel preemption to be disabled on the CPU executing them.

May require interrupts to be disabled too.

Spinlock

Still locked?

Page 400: Embedded Linux Course Slides

400© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Initializing spinlocks

Staticspinlock_t my_lock = SPIN_LOCK_UNLOCKED;

Dynamicvoid spin_lock_init (spinlock_t *lock);

Page 401: Embedded Linux Course Slides

401© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Using spinlocks

void spin_[un]lock (spin_lock_t *lock);

void spin_[un]lock_irqsave (spin_lock_t *lock, unsigned long flags);Disables IRQs on the local CPU

void spin_[un]lock_irq (spin_lock_t *lock);Disables IRQs without saving flags. When you're sure that nobody already disabled interrupts.

void spin_[un]lock_bh (spin_lock_t *lock);Disables software interrupts, but not hardware ones

Note that reader / writer spinlocks also exist.

Page 402: Embedded Linux Course Slides

402© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Deadlock situations

Don't call a function that can try to get access to the same lock

Holding multiple locks is risky!

They can lock up your system. Make sure they never happen!

Get lock1

Wait for lock1

call

Get lock1

Get lock2

Get lock2

Get lock1

DeadLock!

DeadLock!

Page 403: Embedded Linux Course Slides

403© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Alternatives to locking

As we have just seen, locking can have a strong negative impact on system performance. In some situations, you could do without it.

By using lock-free algorithms like Read Copy Update (RCU).RCU API available in the kernel(See http://en.wikipedia.org/wiki/RCU).

When available, use atomic operations.

Page 404: Embedded Linux Course Slides

404© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Atomic variables

Useful when the shared resource is an integer value

Even an instruction like n++ is not guaranteed to be atomic on all processors!

Header

#include <asm/atomic.h>

Type

atomic_tcontains a signed integer (at least 24 bits)

Atomic operations (main ones)

Set or read the counter:atomic_set (atomic_t *v, int i);int atomic_read (atomic_t *v);

Operations without return value:void atomic_inc (atomic_t *v);void atomic_dec (atomic_ *v);void atomic_add (int i, atomic_t *v);void atomic_sub (int i, atomic_t *v);

Simular functions testing the result:int atomic_inc_and_test (...);int atomic_dec_and_test (...);int atomic_sub_and_test (...);

Functions returning the new value:int atomic_inc_and_return (...);int atomic_dec_and_return (...);int atomic_add_and_return (...);int atomic_sub_and_return (...);

Page 405: Embedded Linux Course Slides

405© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Atomic bit operations

Supply very fast, atomic operations

On most platforms, apply to an unsigned long type.Apply to a void type on a few others.

Set, clear, toggle a given bit:void set_bit(int nr, unsigned long * addr);void clear_bit(int nr, unsigned long * addr);void change_bit(int nr, unsigned long * addr);

Test bit value:int test_bit(int nr, unsigned long *addr);

Test and modify (return the previous value):int test_and_set_bit (...);int test_and_clear_bit (...);int test_and_change_bit (...);

Page 406: Embedded Linux Course Slides

406© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux Driver Development

Driver developmentProcesses and scheduling

Page 407: Embedded Linux Course Slides

407© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Processes and Threads

A process is an instance of a running program

Multiple instances of the same program can be running.Program code (“text section”) memory is shared.

Each process has its own data section, address space, open files and signal handlers.

A thread is a single task in a program

It belongs to a process and shares the common data section, address space, open files and pending signals.

It has it's own stack, pending signals and state.

It's common to refer to single threaded programs as processes.

Page 408: Embedded Linux Course Slides

408© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

The Kernel and Threads

The 2.4 kernel did not have a notion of threads.

All threads were implemented as processes that happen to share the same address space, file system resources, file descriptors and signal handlers as their parent process.

In 2.6 an explicit notion of processes and threads was introduced to the kernel.

Scheduling is still done on a thread by thread basis.

The basic object the kernel works with is a task, which is analogous to a thread.

Page 409: Embedded Linux Course Slides

409© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

task_struct

Each task is represented by a task_struct.

The task is linked in the task tree via:

parent Pointer to it's parent

children A linked list

sibling A linked list

task_struct contains a pid field

pid is mapped to task_struct pointer via a hash table

Page 410: Embedded Linux Course Slides

410© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Task Identifiers

Each task_struct has the following identities:

PID Globally unique. Different one for each thread.

TGID Thread Group Id. Returned to user space as getpid()

Shared by all threads of a process.

For single threaded process == PID.

PGID Proccess Group Id. (Posix.1).

SID Session Id (Posix.1).

current points to the current process task_struct

When applicable – not valid in interrupt context.

Page 411: Embedded Linux Course Slides

411© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

A process life

Parent processCalls fork()

and createsa new process

TASK_RUNNINGReady but

not running

TASK_RUNNINGActually running

TASK_INTERRUPTIBLEor TASK_UNINTERRUPTIBLE

Waiting

TASK_ZOMBIETask terminated but its

resources are not freed yet.Waiting for its parent

to acknowledge its death.

Decides to sleepon a wait queue

for a specific event

The event occursor the process receivesa signal. Process becomesrunnable again

The process is preemptedby to scheduler to runa higher priority task

The process is electedby the scheduler

Page 412: Embedded Linux Course Slides

412© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Process context

Process executing in user space...(can be preempted)

Kernel code executedon behalf of user space(can be preempted too!)

System callor exception

User space programs and system calls are scheduled together

Process continuing in user space...(or replaced by a higher priority process)

(can be preempted)

Still has access to processdata (open files...)

Page 413: Embedded Linux Course Slides

413© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Kernel threads

The kernel does not only react from user-space (system calls, exceptions) or hardware events (interrupts). It also runs its own processes.

Kernel space are standard processes scheduled and preempted in the same way (you can view them with top or ps!) They just have no special address space and usually run forever.

Kernel thread examples:

pdflush: regularly flushes “dirty” memory pages to disk (file changes not committed to disk yet).

ksoftirqd: manages soft irqs.

Page 414: Embedded Linux Course Slides

414© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Process priorities

Regular processes

Priorities from -20 (maximum) to 19 (minimum)

Only root can set negative priorities(root can give a negative priority to a regular user process)

Use the nice command to run a job with a given priority:nice -n <priority> <command>

Use the renice command to change a process priority:renice <priority> -p <pid>

Page 415: Embedded Linux Course Slides

415© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Real-time processes

Real-time processes can be started by root using the POSIX API

Available through <sched.h> (see man sched.h for details)

100 real-time priorities available

SCHED_FIFO scheduling class:The process runs until completion unless it is blocked by an I/O, voluntarily relinquishes the CPU, or is preempted by a higher priority process.

SCHED_RR scheduling class:Difference: the processes are scheduled in a Round Robin way.Each process is run until it exhausts a max time quantum. Then other processes with the same priority are run, and so and so...

Page 416: Embedded Linux Course Slides

416© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Timer frequency

Timer interrupts are raised every HZ th of second (= 1 jiffy)

HZ is now configurable (in Processor type and features):100, 250 (i386 default) or 1000.Supported on i386, ia64, ppc, ppc64, sparc64, x86_64See kernel/Kconfig.hz.

Compromise between system responsiveness and global throughput.

Caution: not any value can be used. Constraints apply!

Another idea is to completely turn off CPU timer interrupts when the system is idle (“dynamic tick”): see http://muru.com/linux/dyntick.This saves power. Supports arm and i386 so far.

Page 417: Embedded Linux Course Slides

417© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

O(1) scheduler

The kernel maintains 2 priority arrays:the active and the expired array.

Each array contains 140 entries (100 real-time priorities + 40 regular ones), 1 for each priority, each containing a list of processes with the same priority.

The arrays are implemented in a way that makes it possible to pick a process with the highest priority in constant time (whatever the number of running processes).

Page 418: Embedded Linux Course Slides

418© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Choosing and expiring processes

The scheduler finds the highest process priority

It executes the first process in the priority queue for this priority.

Once the process has exhausted its timeslice, it is moved to the expired array.

The scheduler gets back to selecting another process with the highest priority available, and so on...

Once the active array is empty, the 2 arrays are swapped!Again, everything is done in constant time!

Page 419: Embedded Linux Course Slides

419© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

When is scheduling run?

Each process has a need_resched flag which is set:

After a process exhausted its timeslice.

After a process with a higher priority is awakened.

This flag is checked (possibly causing the execution of the scheduler)

When returning to user-space from a system call

When returning from an interrupt handler (including the cpu timer)

Scheduling also happens when kernel code explicitely runs schedule() or executes an action that sleeps.

Page 420: Embedded Linux Course Slides

420© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Timeslices

The scheduler also prioritizes high priority processes by giving them a bigger timeslice.

Initial process timeslice: parent's timeslice split in 2(otherwise process would cheat by forking).

Minimum priority: 5 ms or 1 jiffie (whichever is larger)

Default priority in jiffies: 100 ms

Maximum priority: 800 ms

Note: actually depends on HZ.See kernel/sched.c for details.

Page 421: Embedded Linux Course Slides

421© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Dynamic priorities

Only applies to regular processes

For a better user experience, the Linux scheduler boots the priority of interactive processes (processes which spend most of their time sleeping, and take time to exhaust their timeslices). Such processes often sleep but need to respond quickly after waking up (example: word processor waiting for key presses).Priority bonus: up to 5 points.

Conversely, the Linux scheduler reduces the priority of compute intensive tasks (which quickly exhaust their timeslices).Priority penalty: up to 5 points.

Page 422: Embedded Linux Course Slides

422© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Driver developmentSleeping

Page 423: Embedded Linux Course Slides

423© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

How to sleep (1)

Sleeping is needed when a user process is waiting for data which are not ready yet. The process then puts itself in a waiting queue.

Static queue declaration

DECLARE_WAIT_QUEUE_HEAD (module_queue);

Dynamic queue declaration

wait_que_head_t queue;init_waitqueue_head(&queue);

Page 424: Embedded Linux Course Slides

424© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

How to sleep (2)

Several ways to make a kernel process sleep

wait_event(queue, condition);Sleeps until the given boolean expression is true.Caution: can't be interrupted (i.e. by killing the client process in user-space)

wait_event_interruptible(queue, condition);Can be interrupted

wait_event_timeout(queue, condition, timeout);Sleeps and automatically wakes up after the given timeout.

wait_event_interruptible_timeout(queue, condition, timeout);Same as above, interruptible.

Page 425: Embedded Linux Course Slides

425© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Waking up!

Typically done by interrupt handlers when data sleeping processes are waiting for are available.

wake_up(&queue);Wakes up all the waiting processes on the given queue

wake_up_interruptible(&queue);Does the same job. Usually called when processes waited using wait_event_interruptible.

Page 426: Embedded Linux Course Slides

426© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Driver developmentInterrupt management

Page 427: Embedded Linux Course Slides

427© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Need for interrupts

Internal processor interrupts used by the processor, for example for multi-task scheduling.

External interrupts needed because most internal and external devices are slower than the processor. Better not keep the processor waiting for input data to be ready or data to be output. When the device is ready again, it sends an interrupt to get the processor attention again.

Page 428: Embedded Linux Course Slides

428© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Interrupt handler constraints

Not run from a user context:Can't transfer data to and from user space(need to be done by system call handlers)

Interrupt handler execution is managed by the CPU, not by the scheduler. Handlers can't run actions that may sleep, because there is nothing to resume their execution.In particular, need to allocate memory with GFP_ATOMIC

Have to complete their job quickly enough:they shouldn't block their interrupt line for too long.

Page 429: Embedded Linux Course Slides

429© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Registering an interrupt handler (1)

Defined in include/linux/interrupt.h

int request_irq( unsigned int irq, Requested irq channel irqreturn_t (*handler) (...), Interrupt handler unsigned long irq_flags, Option mask (see next page) const char * devname, Registered name void *dev_id); Pointer to some handler data

Cannot be NULL and must be unique for shared irqs!

void free_irq( unsigned int irq, void *dev_id);

Page 430: Embedded Linux Course Slides

430© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Registering an interrupt handler (2)

irq_flags bit values (can be combined, none is fine too)

SA_INTERRUPT"Quick" interrupt handler. Run with all interrupts disabled on the current cpu.Shouldn't need to be used except in specific cases (such as timer interrupts)

SA_SHIRQRun with interrupts disabled only on the current irq line and on the local cpu.The interrupt channel can be shared by several devices.Requires a hardware status register telling whether an IRQ was raised or not.

SA_SAMPLE_RANDOMInterrupts can be used to contribute to the system entropy pool used by/dev/random and /dev/urandom. Useful to generate good random numbers. Don't use this if the interrupt behavior of your device is predictable!

Page 431: Embedded Linux Course Slides

431© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

When to register the handler

Either at driver initialization time:consumes lots of IRQ channels!

Or at device open time (first call to the open file operation):better for saving free IRQ channels.Need to count the number of times the device is opened, to be able to free the IRQ channel when the device is no longer in use.

Page 432: Embedded Linux Course Slides

432© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Information on installed handlers

/proc/interrupts

CPU00: 5616905 XT-PIC timer # Registered name1: 9828 XT-PIC i80422: 0 XT-PIC cascade3: 1014243 XT-PIC orinoco_cs7: 184 XT-PIC Intel 82801DB-ICH48: 1 XT-PIC rtc9: 2 XT-PIC acpi11: 566583 XT-PIC ehci_hcd, uhci_hcd, uhci_hcd, uhci_hcd, yenta, yenta, radeon@PCI:1:0:012: 5466 XT-PIC i804214: 121043 XT-PIC ide015: 200888 XT-PIC ide1NMI: 0 # Non Maskable InterruptsERR: 0

Page 433: Embedded Linux Course Slides

433© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Total number of interrupts

cat /proc/stat | grep intr

intr 8190767 6092967 10377 0 1102775 5 2 0 196 ...Total numberof interrupts

IRQ1total

IRQ2total

IRQ3...

Page 434: Embedded Linux Course Slides

434© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Interrupt channel detection (1)

Useful when a driver can be used in different machines / architectures

Some devices announce their IRQ channel in a register

Manual detection

Register your interrupt handler for all possible channels

Ask for an interrupt

Let the called interrupt handler store the IRQ number in a global variable.

Try again if no interrupt was received

Unregister unused interrupt handlers.

Page 435: Embedded Linux Course Slides

435© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Interrupt channel detection (2)

Kernel detection utilities

mask = probe_irq_on();

Activate interrupts on the device

Deactivate interrupts on the device

irq = probe_irq_off(mask);

> 0: unique IRQ number found

= 0: no interrupt. Try again!

< 0: several interrupts happened. Try again!

Page 436: Embedded Linux Course Slides

436© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

The interrupt handler's job

Acknowledge the interrupt to the device(otherwise no more interrupts will be generated)

Read/write data from/to the device

Wake up any waiting process waiting for the completion of this read/write operation:wake_up_interruptible(&module_queue);

Page 437: Embedded Linux Course Slides

437© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Interrupt handler prototype

irqreturn_t (*handler) ( int, /* irq number */ void *dev_id, /* Pointer used to keep track of the corresponding device. Useful when several devices are managed by the same module */ struct pt_regs *regs /* cpu register snapshot, rarely needed*/);

Return value:

IRQ_HANDLED: recognized and handled interrupt

IRQ_NONE: not on a device managed by the module. Useful to share interrupt channels and/or report spurious interrupts to the kernel.

Page 438: Embedded Linux Course Slides

438© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Top half and bottom half processing (1)

Top half: the interrupt handler must complete as quickly as possible. Once it acknowledged the interrupt, it just schedules the lengthy rest of the job taking care of the data, for a later execution.

Bottom half: completing the rest of the interrupt handler job. Handles data, and then wakes up any waiting user process.

Best implemented by softirqs, tasklets, timers or work queues.

Page 439: Embedded Linux Course Slides

439© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Linux Contexts

User Space

User Context

Interrupt Handlers

KernelSpace

InterruptContext

SoftIRQs

Hi p

riota

skle

ts

Net

Sta

ck

Tim

ers

Reg

ula

rta

skle

ts

...

SchedulingPoints

Process Thread

Kernel Thread

Page 440: Embedded Linux Course Slides

440© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Softirq

A fixed set (max 32) of software interrupts (prioritized):

HI_SOFTIRQ Runs low latency tasklets

TIMER_SOFTIRQ Runs timers

NET_TX_SOFTIRQ Network stack Tx

NET_RX_SOFTIRQ Network stack Rx

SCSI_SOFTIRQ SCSI sub system

TASKLET_SOFTIRQ Runs normal tasklets

Activated on return from interrupt (in do_IRQ())

Can run concurrently on SMP systems (even the same softirq).

Page 441: Embedded Linux Course Slides

441© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Tasklets

Added in 2.4

Are run from softirqs (normal or low-latency)

Each tasklet runs only on a single CPU (serialization)

You can initialize a tasklet via:init tasklet_init (struct tasklet_struct *t void (*func)(unsigned long), unsigned long data));

Or declare the tasklet in the module source file:DECLARE_TASKLET (module_tasklet, /* name */ module_do_tasklet, /* function */ 0 /* data */);

Page 442: Embedded Linux Course Slides

442© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Tasklet scheduling and killing

Scheduling a tasklet in the top half part (interrupt handler):

For regular tasklets:tasklet_schedule(&module_tasklet);

Or for low latency tasklets (runs first): tasklet_hi_schedule.

If this tasklet was already scheduled – it is run only once.

If this tasklet was already running – it is rescheduled for later.

On module exit, the tasklet should be killed:

tasklet_kill(&module_tasklet);

Page 443: Embedded Linux Course Slides

443© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Tasklet Masking

Tasklets may be temporarily disabled/enabled:

tasklet_enable(&module_tasklet);

tasklet_disable(&module_tasklet);

tasklet_hi_enable(&module_tasklet);

tasklet_disable_nosync(&module_tasklet);

Page 444: Embedded Linux Course Slides

444© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Timers

Runs via softirq like tasklets

But at a specific time

A timer is represented by a timer_list:

struct timer_list { /* ... */ unsigned long expires; /* In Jiffies */ void (*function )(unsigned int);

unsigned long data; /* Optional */ );

Page 445: Embedded Linux Course Slides

445© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Timer operations

Manipulated with:

void init_timer(struct timer_list *timer);

void add_timer(struct timer_list *timer);

void init_timer_on(struct timer_list *timer, int cpu);

void del_timer(struct timer_list *timer);

void del_timer_sync(struct timer_list *timer);

void mod_timer(struct timer_list *timer, unsigned long expires);

void timer_pending(const struct timer_list *timer);

Page 446: Embedded Linux Course Slides

446© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Work Queues (2.6 only)

Each work queue has a kernel thread (task) per cpu.

Since 2.6.6 also a single threaded version exists.

Code in work queue:

Has a process context.

May sleep.

New work queues may be created/destroyed via:

struct workqueue_struct *create_workqueue(const char * name);

struct workqueue_struct *create_singlethread_workqueue(const char * name);

void destroy_workqueue(const char * name);

Page 447: Embedded Linux Course Slides

447© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Working the Workqueue

Work is delivered to a workqueue via:

DECLARE_WORK(work, func, data);

INIT_WORK(work, func, data);

int queue_work(struct workqueue_struct *wq, struct work_struct *work);

int queue_delayed_work(struct workqueue_struct *wq, struct work_struct *work, unsigned long delay);

int flush_workqueue(struct workqueue_struct *wq);

Page 448: Embedded Linux Course Slides

448© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

The Default Workqueue

One “default” work queue is run by the keventd kernel thread

For keventd, we have the more common:

int schedule_work(struct work_struct *work);

int schedule_delayed_work(struct work_struct *work, unsigned long delay);

int cancel_delayed_work(struct work_struct *work);

int flush_scheduled_work(void);

int current_is_keventd(void);

Page 449: Embedded Linux Course Slides

449© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Disabling interrupts

May be useful in regular driver code...

Can be useful to ensure that an interrupt handler will not preempt your code (including kernel preemption)

Disabling interrupts on the local CPU:unsigned long flags;local_irq_save(flags); // Interrupts disabled...local_irq_restore(flags); // Interrupts restored to their previous state.Note: must be run from within the same function!

Page 450: Embedded Linux Course Slides

450© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Masking out an interrupt line

Useful to disable interrupts on a particular device

void disable_irq (unsigned int irq);Disables the irq line for all processors in the system.Waits for all currently executing handlers to complete.

void disable_irq_nosync (unsigned int irq);Same, except it doesn't wait for handlers to complete.

void enable_irq (unsigned int irq);Restores interrupts on the irq line.

void synchronize_irq (unsigned int irq);Waits for irq handlers to complete (if any).

Page 451: Embedded Linux Course Slides

451© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Checking interrupt status

Can be useful for code which can be run from both process or interrupt context, to know whether it is allowed or not to call code that may sleep.

irqs_disabled()Tests whether local interrupt delivery is disabled.

in_interrupt()Tests whether code is running in interrupt context

in_irq()Tests whether code is running in an interrupt handler.

Page 452: Embedded Linux Course Slides

452© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Interrupt management fun

In a training lab, somebody forgot to unregister a handler on a shared interrupt line in the module exit function.

In a training lab, somebody freed the timer interrupt handler by mistake (using the wrong irq number). The system froze. Remember the kernel is not protected against itself!

Page 453: Embedded Linux Course Slides

453© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Interrupt management summary

Device driver

When the device file is first open, register an interrupt handler for the device's interrupt channel.

Interrupt handler

Called when an interrupt is raised.

Acknowledge the interrupt

If needed, schedule a tasklet taking care of handling data. Otherwise, wake up processes waiting for the data.

Tasklet

Process the data

Wake up processes waiting for the data

Device driver

When the device is no longer opened by any process, unregister the interrupt handler.

Page 454: Embedded Linux Course Slides

454© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Driver developmentmmap

Page 455: Embedded Linux Course Slides

455© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

mmap (1)

Possibility to have parts of the virtual address space of a program mapped to the contents of a file!

> cat /proc/1/maps (init process)start end perm offset major:minor inode mapped file name00771000-0077f000 r-xp 00000000 03:05 1165839 /lib/libselinux.so.10077f000-00781000 rw-p 0000d000 03:05 1165839 /lib/libselinux.so.10097d000-00992000 r-xp 00000000 03:05 1158767 /lib/ld-2.3.3.so00992000-00993000 r--p 00014000 03:05 1158767 /lib/ld-2.3.3.so00993000-00994000 rw-p 00015000 03:05 1158767 /lib/ld-2.3.3.so00996000-00aac000 r-xp 00000000 03:05 1158770 /lib/tls/libc-2.3.3.so00aac000-00aad000 r--p 00116000 03:05 1158770 /lib/tls/libc-2.3.3.so00aad000-00ab0000 rw-p 00117000 03:05 1158770 /lib/tls/libc-2.3.3.so00ab0000-00ab2000 rw-p 00ab0000 00:00 008048000-08050000 r-xp 00000000 03:05 571452 /sbin/init (text)08050000-08051000 rw-p 00008000 03:05 571452 /sbin/init (data, stack)08b43000-08b64000 rw-p 08b43000 00:00 0f6fdf000-f6fe0000 rw-p f6fdf000 00:00 0fefd4000-ff000000 rw-p fefd4000 00:00 0ffffe000-fffff000 ---p 00000000 00:00 0

Page 456: Embedded Linux Course Slides

456© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

mmap (2)

Particularly useful when the file is a device file!Allows to access device I/O memory and ports without having to go through (expensive) read, write or ioctl calls!

X server example (maps excerpt)

start end perm offset major:minor inode mapped file name08047000-081be000 r-xp 00000000 03:05 310295 /usr/X11R6/bin/Xorg081be000-081f0000 rw-p 00176000 03:05 310295 /usr/X11R6/bin/Xorg...f4e08000-f4f09000 rw-s e0000000 03:05 655295 /dev/dri/card0f4f09000-f4f0b000 rw-s 4281a000 03:05 655295 /dev/dri/card0f4f0b000-f6f0b000 rw-s e8000000 03:05 652822 /dev/memf6f0b000-f6f8b000 rw-s fcff0000 03:05 652822 /dev/mem

A more user friendly way to get such information: pmap <pid>

Page 457: Embedded Linux Course Slides

457© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

How to implement mmap - User space

Open the device file

Call the mmap system call (see man mmap for details):void * mmap(

void *start, /* Often 0, preferred starting address */size_t length, /* Length of the mapped area */int prot , /* Permissions: read, write, execute */int flags, /* Options: shared mapping, private copy... */int fd, /* Open file descriptor */off_t offset /* Offset in the file */

);

Read from the return virtual address or write to it.

Page 458: Embedded Linux Course Slides

458© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

How to implement mmap - Kernel space

Character driver: implement a mmap file operationand add it to the driver file operations:int (*mmap) (

struct file *, /* Open file structure */struct vm_area_struct /* Kernel VMA structure */

);

Initialize the mapping.Can be done in most cases with the remap_pfn_range() function, which takes care of most of the job.

Page 459: Embedded Linux Course Slides

459© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

remap_pfn_range()

pfn: page frame numberThe most significant bits of the page address(without the bits corresponding to the page size).

#include <linux/mm.h>

int remap_pfn_range(struct vm_area_struct *, /* VMA struct */unsigned long virt_addr, /* Starting user virtual address */unsigned long pfn, /* pfn of the starting physical address */unsigned long size, /* Mapping size */pgprot_t /* Page permissions */

);

Page 460: Embedded Linux Course Slides

460© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Simple mmap implementation

static int acme_mmap (struct file * file, struct vm_area_struct * vma)

{size = vma->vm_start - vma->vm_end;

if (size > ACME_SIZE) return -EINVAL;

if (remap_pfn_range(vma,vma->vm_start,ACME_PHYS >> PAGE_SHIFT,size,vma->vm_page_prot))

return -EAGAIN;return 0;

}

Page 461: Embedded Linux Course Slides

461© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Block Devices and File Systems

Page 462: Embedded Linux Course Slides

462© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Block device or MTD filesystems

Block devices

Floppy or hard disks(SCSI, IDE)

Compact Flash (seen as a regular IDE drive)

RAM disks

Loopback devices

Memory Technology Devices (MTD)

Flash, ROM or RAM chips

MTD emulation on block devices

Filesystems are either made for block or MTD storage devices.See Documentation/filesystems/ for details.

Page 463: Embedded Linux Course Slides

463© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

I/O schedulers

Mission of I/O schedulers: re-order reads and writes to disk to minimize disk head moves (time consuming!)

2.4 has one fixed: the Linus Elevator.

2.6 has modular IO scheduler No-op, Elevator, Antciptory, Deadline, CFQ

Slower Faster

Page 464: Embedded Linux Course Slides

464© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Traditional block filesystems

Traditional filesystems

Hard to recover from crashes. Can be left in a corrupted (“half finished”) state after a system crash or sudden power-off.

ext2: traditional Linux filesystem(repair it with fsck.ext2)

vfat: traditional Windows filesystem(repair it with fsck.vfat on GNU/Linux or Scandisk on Windows)

Page 465: Embedded Linux Course Slides

465© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Journaled filesystems

Designed to stay in a correct state even after system crashes or a sudden power-off

All writes are first described in the journal before being committed to files

Write an entryin the journal

Writeto file

Application

Write to fileUser-space

Kernel space(filesystem)

Clearjournal entry

Page 466: Embedded Linux Course Slides

466© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Filesystem recovery after crashes

Reboot

Journalempty?

Executejournal

Filesystem OK

Yes

Thanks to the journal, the filesystem is never left in a corrupted state

Recently saved data could still be lostDiscard

incompletejournal entries

No

Page 467: Embedded Linux Course Slides

467© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Journaled block filesystems

Journaled filesystems

ext3: ext2 with journal extension

reiserFS: most innovative (fast and extensible)

Others: JFS (IBM), XFS (SGI)

NTFS: well supported by Linux in read-mode

Page 468: Embedded Linux Course Slides

468© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Compressed block filesystems (1)

Cramfs

Simple, small, read-only compressed filesystemdesigned for embedded systems .

Maximum filesystem size: 256 MB

Maximum file size: 16 MB

See Documentation/filesystems/cramfs.txtin kernel sources.

Page 469: Embedded Linux Course Slides

469© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Compressed block filesystems (2)

Squashfs: http://squashfs.sourceforge.net

A must-use replacement for Cramfs! Also read-only.

Maximum filesystem and file size: 232 bytes (4 GB)

Achieves better compression and much better performance.

Fully stable but released as a separate patch so far (waiting for Linux 2.7 to start).

Successfully tested on i386, ppc, arm and sparc.

See benchmarks on http://tree.celinuxforum.org/CelfPubWiki/SquashFsComparisons

Page 470: Embedded Linux Course Slides

470© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

ramdisk filesystems

Useful to store temporary data not kept after power off or reboot: system log files, connection data, temporary files...

Traditional block filesystems: journaling not needed.Many drawbacks: fixed in size. Remaining space not usable as RAM. Files duplicated in RAM (in the block device and file cache)!

tmpfs (Config: File systems -> Pseudo filesystems)Doesn't waste RAM: grows and shrinks to accommodate stored filesSaves RAM: no duplication; can swap out pages to disk when needed.

See Documentation/filesystems/tmpfs.txt in kernel sources.

Page 471: Embedded Linux Course Slides

471© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Mixing read-only and read-write filesystems

Good idea to split your block storage into

A compressed read-only partition (Squashfs)Typically used for the root filesystem (binaries, kernel...).Compression saves space. Read-only access protects your system from mistakes and data corruption.

A read-write partition with a journaled filesystem (like ext3)Used to store user or configuration data.Guarantees filesystem integrity after power off or crashes.

A ramdisk for temporary files (tmpfs)

Squashfsread-only

compressedroot

filesystem

ext3read-writeuser and

configurationdata

tmpfsread-write

volatile data

Blo

ck S

tora

gera

mdi

sk

Page 472: Embedded Linux Course Slides

472© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

The MTD subsystem

MTD Chip drivers

Linux filesystem interface

CFI flash

MTD “User” modules

Memory devices hardware

Flash Translation Layersfor block device emulationCaution: patented algorithms!

NFTLFTL INFTL

DiskOnChip flash

RAM chips

ROM chipsNAND flash

Block device Virtual memory

Virtual devices appearing as MTD devices

jffs2 Char device Block device

Read-only block deviceyaffs2

Page 473: Embedded Linux Course Slides

473© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

MTD filesystems - jffs2

jffs2: Journaling Flash File System v2

Designed to write flash sectors in an homogeneous way.Flash bits can only be rewritten a relatively small number of times (often < 100 000).

Compressed to fit as many data as possible on flash chips. Also compensates for slower access time to those chips.

Power down reliable: can restart without any intervention

Shortcomings: low speed, big RAM consumption (4 MB for 128 MB of storage).

Page 474: Embedded Linux Course Slides

474© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Mounting a jffs2 image

Useful to create or edit jffs2 images on your GNU / Linux PC!

Mounting an MTD device as a loop device is a bit complex task. Here's an example for jffs2:

modprobe loopmodprobe mtdblocklosetup /dev/loop0 <file>.jffs2modprobe blkmtd erasesz=256 device=/dev/loop0mknod /dev/mtdblock0 b 31 0 (if not done yet)mkdir /mnt/jffs2 (example mount point, if not done yet)mount -t jffs2 /dev/mtdblock0 /mnt/jffs2/

It's very likely that your standard kernel misses one of these modules. Check the corresponding .c file in the kernel sources and look in the corresponding Makefile which option you need to recompile your kernel with.

Page 475: Embedded Linux Course Slides

475© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

MTD filesystems - yaffs2

yaffs2: Yet Another Flash Filing System, version 2

yaffs2 home: http://aleph1.co.uk/drupal/?q=node/35Caution: site under reconstruction. Lots of broken links!

Features: NAND flash only. No compression. Several times faster than jffs2 (mainly significant in boot time) Consumes much less RAM. Also includes ECC and is power down reliable.

License: GPL or proprietary

Ships outside the Linux kernel. Get it from CVS:http://aleph1.co.uk/cgi-bin/viewcvs.cgi/yaffs/

Page 476: Embedded Linux Course Slides

476© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Filesystem choices for block flash devices

Typically for Compact Flash storage

Can't use jffs2 or yaffs2 on CF storage (block device). MTD Block device emulation could be used, but jffs2 / yaffs2 writing schemes could interfere with on-chip flash management (manufacturer dependent).

Never use block device journaled filesystems on unprotected flash chips!

noatime: doesn't write access time information in file inodessync: to perform writes immediately (reduce power down failure risks)

Page 477: Embedded Linux Course Slides

477© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Filesystem choice summary

Storagetype?

choose jffs2 or yaffs2read-only or read-write

Read-onlyfiles?

MTD

BlockContains

flash?

choose Squashfsread-only

choose ext2noatime + sync mount options

Volatiledata?

Choose tmpfs

Choose ext3 or reiserfs

No

Yes

Yes

No

Yes

No

Page 478: Embedded Linux Course Slides

478© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

The Network subsystemand Network device drivers

Page 479: Embedded Linux Course Slides

479© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

A view of the Linux networking subsystem

Driver <> Hardware

Driver <> Stack

Networking Stack

Stack <> App App2 App3App 1

Networking Stack

IP

TCP ICMPUDP

Driver

Socket Layer

Bridge

Page 480: Embedded Linux Course Slides

480© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Network Device Driver Hardware Interface

Send

Free

Send

Free

Send

RcvOk

SentOK

RcvErr

SendErr

RecvCRC

Free

RcvOK

Driver

Tx

Rx

xxx xxx xxx xxx xxx

xxx xxx xxx xxx

Memory Access

DMA�Driver allocates Ring Buffers.�Driver resets descriptors to initial state.�Driver puts packet to be sent in Tx buffers.�Device puts received packet in Rx buffers.�Driver/Device update descriptors to indicate state.�Usually, device indicates Rx and end of Tx with interrupt, unless polling or NAPI.

Page 481: Embedded Linux Course Slides

481© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Network Device Driver Stack Interface

A network device driver provides interface to the network stack.

It does not have or use major/minor numbers, like character devices.

A network driver is represented by a:

struct net_device

And is registered via:

int register_netdev(struct net_device *dev);

int unregister_netdev(struct net_device dev);

After filling in some important bits...

Page 482: Embedded Linux Course Slides

482© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Socket Buffers

We need to manipulate packets through the stack

This manipulation involves efficiently:

Adding protocol headers/trailers down the stack.

Removing protocol headers/trailers up the stack.

Packets can be chained together.

Each protocol should have convenient access to header fields.

To do all this the kernel provides the sk_buff structure.

Page 483: Embedded Linux Course Slides

483© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

sk_buff

An sk_buff represents a single packet.

This struct is passed through the protocol stack.

It holds pointers to a buffer with the packet data:

headroom tailroom

sk_buff

headdata tail

endmac

nh

h

mac ip tcp telnet

Page 484: Embedded Linux Course Slides

484© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

sk_buff Manipulation

Manipulate sk_buff:

unsigned char *skb_put(struct sk_buff * skb, unsigned int len);

tail += len

unsigned char *skb_push(struct sk_buff * skb, unsigned int len);

data -= len

unsigned char *skb_pull(struct sk_buff * skb, unsigned int len);

data += len

Page 485: Embedded Linux Course Slides

485© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

sk_buff Manipulation

Manipulate sk_buff:

int skb_headroom(const struct sk_buff *skb);

data - head

int skb_tailroom(const struct sk_buff *skb);

end - tail

int skb_reserve(const struct sk_buff *skb, unsigned int len);

tail = (data +=len)

Page 486: Embedded Linux Course Slides

486© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

sk_buff Allocation

Low level allocation is done via:

struct sk_buff *alloc_skb(unsigned int size, int gfp_mask);

But it is better to use the wrapper:

struct sk_buff *dev_alloc_skb(unsigned int size);

Which reserves some space for optimization.

Page 487: Embedded Linux Course Slides

487© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

sk_buff Allocation Example

Immediately after allocation, we should reserve the needed headroom:

struct sk_buff*skb;

skb = dev_alloc_skb(1500);

if(unlikely(!skb))

break;

/* Mark as being used by this device */

skb->dev = dev;

/* Align IP on 16 byte boundaries */

skb_reserve(skb, 2);

Page 488: Embedded Linux Course Slides

488© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Softnet

Was introduced in kernel 2.4.x

Parallelize packet handling on SMP machines

Packet transmit/receive is handled via two softirqs:

NET_TX_SOFTIRQ Feeds packets from network stack to driver.

NET_RX_SOFTIRQ Feeds packets from driver to network stack.

The transmit/receive queues are stored in per-cpu softnet_data.

Page 489: Embedded Linux Course Slides

489© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Packet Reception

The driver:

Allocates an skb.

sets up a descriptor in the ring buffers for the hardware.

The driver Rx interrupt handler calls netif_rx(skb).

netif_rx(skb)

Deposits the sk_buff in the per-cpu input queue.

Marks the NET_RX_SOFTIRQ to run.

Later net_rx_action() is called by NET_RX_SOFTIEQ, which calls the driver poll() method to feed the packet up.

Normally poll() is set to proccess_backlog() by net_dev_init()

Page 490: Embedded Linux Course Slides

490© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Packet Reception Overview

Page 491: Embedded Linux Course Slides

491© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Packet Transmission

Each network device defines a method:

int (*hard_start_xmit) (struct sk_buff *skb, struct net_device *dev);

This method is indirectly called from the NET_TX_SOFTIRQ

Calls to this method are serialized via dev->xmit_lock_owner

The driver can manage the transmit queue:

void netif_start_queue(struct net_device *net);

void netif_stop_queue(struct net_device *net);

void netif_wake_queue(struct net_device *net);

int netif_queue_stopped(struct net_device *net);

Page 492: Embedded Linux Course Slides

492© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Packet Reception Overview

Page 493: Embedded Linux Course Slides

493© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Network Device Allocation

Each network device is represented by a struct net_device

They are allocated using:

struct net_device *alloc_netdev(size, mask, setup_func);

size – size of our priv data part

mask – a naming pattern (e.g. “eth%d”)

setup_func – A function to prepare the rest of net_device.

And deallocated with

void free_netdev(struct *net_device);

Page 494: Embedded Linux Course Slides

494© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Network Device Allocation (cont.)

For Ethernet we have a short version:

struct net_device *alloc_etherdev(size);

which calls alloc_netdev(size, “eth%d”, ether_setup);

Page 495: Embedded Linux Course Slides

495© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Network Device Initialization

The net_device should be filled with numerous methods:

open – request resources, register interrupts, start queues.

stop – deallocates resources, unregister irq, stop queue.

get_stats – report statistics

set_multicast_list – configure device for multicast

do_ioctl – device specific IOCTL function

change_mtu – Control device MTU setting

hard_start_xmit – called by the stack to initiate Tx.

Page 496: Embedded Linux Course Slides

496© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Network Device Initialization (Cont.)

Also, the dev->flags should be set according to device capabilities:

IFF_MULTICAST – Device support multicast

IFF_NOARP – Device does not support ARP protocol

Page 497: Embedded Linux Course Slides

497© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

NAPI

Net network API

Optional – provides interrupt mitigation under high load

Requirements:

A DMA ring buffer.

Ability to turn off receive interrupts.

It is used by defining a new method:

int (*poll) (struct net_device *dev, int * budget);

Called by the network stack periodically when signaled by the driver to do so.

Page 498: Embedded Linux Course Slides

498© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

NAPI (cont.)

When a receive interrupt occurs, driver:

Turns off receive interrupts.

Calls netif_rx_schedule(dev) to get stack to start calling it's poll method.

Poll method

Scans receive ring buffers, feeding packets to the stack via: netif_receive_skb(skb).

If work finished within budget parameter, re-enables interrupts and calls netif_rex_complete(dev)

Else, stack will call poll method again.

Page 499: Embedded Linux Course Slides

499© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Advice and resourcesGetting help and contributions

Page 500: Embedded Linux Course Slides

500© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Solving issues

If you face an issue, and it doesn't look specific to your work but rather to the tools you are using, it is very likely that someone else already faced it.

Search the Internet for similar error reports

On web sites or mailing list archives(using a good search engine)

On newsgroups: http://groups.google.com/

You have great chances of finding a solution or workaround, or at least an explanation for your issue.

Otherwise, reporting the issue is up to you!

Page 501: Embedded Linux Course Slides

501© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Getting help

If you have a support contract, ask your vendor

Otherwise, don't hesitate to share your questions and issues on mailing lists

Either contact the Linux mailing list for your architecture (like linux-arm-kernel or linuxsh-dev...)

Or contact the mailing list for the subsystem you're dealing with (linux-usb-devel, linux-mtd...). Don't ask the maintainer directly!

Most mailing lists come with a FAQ page. Make sure you read it before contacting the mailing list

Refrain from contacting the Linux Kernel mailing list, unless you're an experienced developer and need advice

Page 502: Embedded Linux Course Slides

502© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Advice and resourcesBug report and patch submission

Page 503: Embedded Linux Course Slides

503© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Reporting Linux bugs

First make sure you're using the latest version

Make sure you investigate the issue as much as you can:see Documentation/BUG-HUNTING

Make sure the bug has not been reported yet. A bug tracking system(http://bugzilla.kernel.org/) exists but very few kernel developers use it. Best to use web search engines (accessing public mailing list archives)

If the subsystem you report a bug on has a mailing list, use it. Otherwise, contact the official maintainer (see the MAINTAINERS file). Always give as many useful details as possible.

Page 504: Embedded Linux Course Slides

504© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

How to submit patches or drivers

Don't merge patches addressing different issues

You should identify and contact the official maintainer for the files to patch.

See Documentation/SubmittingPatches for details. For trivial patches, you can copy the Trivial Patch Monkey.

Special subsystems:

ARM platform: it's best to submit your ARM patches to Russell King's patch system: http://www.arm.linux.org.uk/developer/patches/

Page 505: Embedded Linux Course Slides

505© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

How to become a kernel developer?

Greg Kroah-Hartman gathered useful references and advice for people interested in contributing to kernel development:

Documentation/HOWTO (in kernel sources since 2.6.15-rc2)

Do not miss this very useful document!

Page 506: Embedded Linux Course Slides

506© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Advice and resourcesReferences

Page 507: Embedded Linux Course Slides

507© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Information sites (1)

Linux Weekly Newshttp://lwn.net/

The weekly digest off all Linux and free software information sources

In depth technical discussions about the kernel

Subscribe to finance the editors ($5 / month)

Articles available for non subscribers after 1 week.

Page 508: Embedded Linux Course Slides

508© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Information sites (2)

KernelTraphttp://kerneltrap.org/

Forum website for kernel developers

News, articles, whitepapers, discussions, polls, interviews

Perfect if a digest is not enough!

Page 509: Embedded Linux Course Slides

Useful reading (1)

Linux Device Drivers, 3rd edition, Feb 2005

By Jonathan Corbet, Alessandro Rubini, Greg Kroah-Hartman, O'Reillyhttp://www.oreilly.com/catalog/linuxdrive3/

Freely available on-line!Great companion to the printed book for easy electronic searches!http://lwn.net/Kernel/LDD3/ (1 PDF file per chapter)http://free-electrons.com/community/kernel/ldd3/ (single PDF file)

A must-have book for Linux device driver writers!

Page 510: Embedded Linux Course Slides

Useful reading (2)

Linux Kernel Development, 2nd Edition, Jan 2005Robert Love, Novell Presshttp://rlove.org/kernel_book/A very synthetic and pleasant way to learn about kernelsubsystems (beyond the needs of device driver writers)

Understanding the Linux Kernel, 3rd edition, Nov 2005Daniel P. Bovet, Marco Cesati, O'Reillyhttp://oreilly.com/catalog/understandlk/An extensive review of Linux kernel internals, covering Linux 2.6 at last.

Unfortunately, only covers the PC architecture.

Page 511: Embedded Linux Course Slides

Useful reading (3)

Building Embedded Linux Systems, April 2003Karim Yaghmour, O'Reillyhttp://www.oreilly.com/catalog/belinuxsys/Not very fresh, but doesn't depend too much on kernel versions

See http://www.linuxdevices.com/articles/AT2969812114.htmlfor more embedded Linux books.

Page 512: Embedded Linux Course Slides

512© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Useful on-line resources

Linux kernel mailing list FAQhttp://www.tux.org/lkml/Complete Linux kernel FAQRead this before asking a question to the mailing list

Kernel Newbieshttp://kernelnewbies.org/Glossaries, articles, presentations, HOWTOs,recommended reading, useful tools for peoplegetting familiar with Linux kernel or driverdevelopment.

Page 513: Embedded Linux Course Slides

513© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

CE Linux Forum resources

CE Linux Forum's Wikiis full of useful resources for embedded systems developers:

Kernel patches not available in mainstream yet

Many howto documents of all kinds

Details about ongoing projects, such as reducing kernel size, boot time, or power consumption.

Contributions are welcome!

http://tree.celinuxforum.org/CelfPubWiki

Page 514: Embedded Linux Course Slides

514© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

ARM resources

ARM Linux project: http://www.arm.linux.org.uk/

Developer documentation: http://www.arm.linux.org.uk/developer/

arm-linux-kernel mailing list:http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel

FAQ: http://www.arm.linux.org.uk/armlinux/mlfaq.php

How to post kernel fixes:http://www.arm.uk.linux.org/developer/patches/

ARMLinux @ Simtec: http://armlinux.simtec.co.uk/A few useful resources: FAQ, documentation and Who's who!

Page 515: Embedded Linux Course Slides

515© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

International conferences (1)

Useful conferences featuring Linux kernel presentations

Ottawa Linux Symposium (July): http://linuxsymposium.org/Right after the (private) kernel summit.Lots of kernel topics. Many core kernel hackers still present.

Fosdem: http://fosdem.org (Brussels, February)For developers. Kernel presentations from well-known kernel hackers.

CE Linux Forum: http://celinuxforum.org/Organizes several international technical conferences, in particular in California (San Jose) and in Japan. Now open to non CELF members!Very interesting kernel topics for embedded systems developers.

Page 516: Embedded Linux Course Slides

516© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

International conferences (2)

Don't miss our free conference videos onhttp://free-electrons.com/community/videos/conferences/!

Page 517: Embedded Linux Course Slides

517© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

Advice and resourcesLast advice

Page 518: Embedded Linux Course Slides

518© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Use the Source, Luke!

Many resources and tricks on the Internet find you will, but solutions to all technical issues only in the Source lie.

Thanks to LucasArts

Page 519: Embedded Linux Course Slides

519© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

AnnexesQuiz answers

Page 520: Embedded Linux Course Slides

520© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Quiz answers

request_irq, free_irqQ: Why does dev_id have to be unique for shared IRQs?A: Otherwise, the kernel would have no way of knowing which handler to release. Also needed for multiple devices (disks, serial ports...) managed by the same driver, which rely on the same interrupt handler code.

Interrupt handlingQ: Why did the kernel segfault at module unload (forgetting to unregister a handler in a shared interrupt line)?A: Kernel memory is allocated at module load time, to host module code. This memory is freed at module unload time. If you forget to unregister a handler and an interrupt comes, the cpu will try to jump to the address of the handler, which is in a freed memory area. Crash!

Page 521: Embedded Linux Course Slides

521© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

AnnexesMore Shell Tips & Tricks

Page 522: Embedded Linux Course Slides

522© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

ls command

ls -a (all)Lists all the files (including .* files)

ls -l (long)Long listing (type, date, size, owner, permissions)

ls -t (time)Lists the most recent files first

ls -S (size)Lists the biggest files first

ls -r (reverse)Reverses the sort order

ls -ltr (options can be combined)Long listing, most recent files at the end

Lists the files in the current directory, in alphanumeric order,except files starting with the “.” character.

Page 523: Embedded Linux Course Slides

523© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

File name pattern substitutions

Better introduced by examples!

ls *txtThe shell first replaces *txt by all the file and directory names ending by txt (including .txt), except those starting with ., and then executes the ls command line.

ls -d .*Lists all the files and directories starting with .-d tells ls not to display the contents of directories.

cat ?.logDisplays all the files which names start by 1 character and end by .log

Page 524: Embedded Linux Course Slides

524© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Special directories (1)

./

The current directory. Useful for commands taking a directory argument. Also sometimes useful to run commands in the current directory (see later).

So ./readme.txt and readme.txt are equivalent.

../

The parent (enclosing) directory. Always belongs to the . directory (see ls -a). Only reference to the parent directory.

Typical usage:cd ..

Page 525: Embedded Linux Course Slides

525© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

The cd and pwd commands

cd <dir>Change the current directory to <dir>.

pwdDisplays the current directory ("working directory").

Page 526: Embedded Linux Course Slides

526© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

The cp command

cp <source_file> <target_file>Copies the source file to the target.

cp file1 file2 file3 ... dirCopies the files to the target directory (last argument).

cp -i (interactive)Asks for user confirmation if the target file already exists

cp -r <source_dir> <target_dir> (recursive)Copies the whole directory.

Page 527: Embedded Linux Course Slides

527© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

mv and rm commands

mv <old_name> <new_name> (move)Renames the given file or directory.

mv -i (interactive)If the new file already exits, asks for user confirm

rm file1 file2 file3 ... (remove)Removes the given files.

rm -i (interactive)Always ask for user confirm.

rm -r dir1 dir2 dir3 (recursive)Removes the given directories with all their contents.

Page 528: Embedded Linux Course Slides

528© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Creating and removing directories

mkdir dir1 dir2 dir3 ... (make dir)Creates directories with the given names.

rmdir dir1 dir2 dir3 ... (remove dir)Removes the given directoriesSafe: only works when directories and empty.Alternative: rm -r (doesn't need empty directories).

Page 529: Embedded Linux Course Slides

529© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Displaying file contents

Several ways of displaying the contents of files.

cat file1 file2 file3 ... (concatenate)Concatenates and outputs the contents of the given files.

more file1 file2 file3 ...After each page, asks the user to hit a key to continue.Can also jump to the first occurrence of a keyword(/ command).

less file1 file2 file3 ...Does more than more with less.Doesn't read the whole file before starting.Supports backward movement in the file (? command).

Page 530: Embedded Linux Course Slides

530© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

The head and tail commands

head [-<n>] <file>Displays the first <n> lines (or 10 by default) of the given file.Doesn't have to open the whole file to do this!

tail [-<n>] <file>Displays the last <n> lines (or 10 by default) of the given file.No need to load the whole file in RAM! Very useful for huge files.

tail -f <file> (follow)Displays the last 10 lines of the given file and continues to display new lines when they are appended to the file.Very useful to follow the changes in a log file, for example.

Exampleshead windows_bugs.txttail -f outlook_vulnerabilities.txt

Page 531: Embedded Linux Course Slides

531© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

The grep command

grep <pattern> <files>Scans the given files and displays the lines which match the given pattern.

grep error *.logDisplays all the lines containing error in the *.log files

grep -i error *.logSame, but case insensitive

grep -ri error .Same, but recursively in all the files in . and its subdirectories

grep -v info *.logOutputs all the lines in the files except those containing info.

Page 532: Embedded Linux Course Slides

532© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

The sort command

sort <file>Sorts the lines in the given file in character order and outputs them.

sort -r <file>Same, but in reverse order.

sort -ru <file>u: unique. Same, but just outputs identical lines once.

More possibilities described later!

Page 533: Embedded Linux Course Slides

533© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Symbolic links

A symbolic link is a special file which is just a reference to the name of another one (file or directory):

Useful to reduce disk usage and complexity when 2 files have the same content.

Example:anakin_skywalker_biography -> darth_vador_biography

How to identify symbolic links:

ls -l displays -> and the linked file name.

GNU ls displays links with a different color.

Page 534: Embedded Linux Course Slides

534© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Creating symbolic links

To create a symbolic link (same order as in cp):ln -s file_name link_name

To create a link with to a file in another directory, with the same name:ln -s ../README.txt

To create multiple links at once in a given directory:ln -s file1 file2 file3 ... dir

To remove a link:rm link_nameOf course, this doesn't remove the linked file!

Page 535: Embedded Linux Course Slides

535© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Hard links

The default behavior for ln is to create hard links

A hard link to a file is a regular file with exactly the same physical contents

While they still save space, hard links can't be distinguished from the original files.

If you remove the original file, there is no impact on the hard link contents.

The contents are removed when there are no more files (hard links) to them.

Page 536: Embedded Linux Course Slides

536© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Files names and inodes

Makes hard and symbolic (soft) links easier to understand!

Inode

File Hard linkSoft link

Inodeinterface

File name interface

Filesystem

Users

rmrm

Page 537: Embedded Linux Course Slides

537© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

File access rights

3 types of access rights

Read access (r)

Write access (w)

Execute rights (x)

3 types of access levels

User (u): for the owner of the file

Group (g): each file also has a “group” attribute, corresponding to a given list of users

Others (o): for all other users

Use ls -l to check file access rights

Page 538: Embedded Linux Course Slides

538© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Access right constraints

x without r is legal but is uselessYou have to be able to read a file to execute it.

Both r and x permissions needed for directories:x to enter, r to list its contents.

You can't rename, remove, copy files in a directory if you don't have w access to this directory.

If you have w access to a directory, you CAN remove a file even if you don't have write access to this file (remember that a directory is just a file describing a list of files). This even lets you modify (remove + recreate) a file even without w access to it.

Page 539: Embedded Linux Course Slides

539© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Access rights examples

-rw-r--r--Readable and writable for file owner, only readable for others

-rw-r-----Readable and writable for file owner, only readable for users belonging to the file group.

drwx------Directory only accessible by its owner

-------r-xFile executable by others but neither by your friends nor by yourself. Nice protections for a trap...

Page 540: Embedded Linux Course Slides

540© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

chmod: changing permissions

chmod <permissions> <files>2 formats for permissions:

Octal format (abc): a,b,c = r*4+w*2+x (r, w, x: booleans)Example: chmod 644 <file>(rw for u, r for g and o)

Or symbolic format. Easy to understand by examples:chmod go+r: add read permissions to group and others.chmod u-w: remove write permissions from user.chmod a-x: (a: all) remove execute permission from all.

Page 541: Embedded Linux Course Slides

541© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

More chmod (1)

chmod -R a+rX linux/Makes linux and everything in it available to everyone!

R: apply changes recursively

X: x, but only for directories and files already executableVery useful to open recursive access to directories, without adding execution rights to all files.

Page 542: Embedded Linux Course Slides

542© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

More chmod (2)

chmod a+t /tmp

t: (sticky). Special permission for directories, allowing only the directory and file owner to delete a file in a directory.

Useful for directories with write access to anyone,like /tmp.

Displayed by ls -l with a t character.

Page 543: Embedded Linux Course Slides

543© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Standard output

More about command output

All the commands outputting text on your terminal do it by writing to their standard output.

Standard output can be written (redirected) to a file using the > symbol

Standard output can be appended to an existing file using the >> symbol

Page 544: Embedded Linux Course Slides

544© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Standard output redirection examples

ls ~saddam/* > ~gwb/weapons_mass_destruction.txt

cat obiwan_kenobi.txt > starwars_biographies.txtcat han_solo.txt >> starwars_biographies.txt

echo “README: No such file or directory” > READMEUseful way of creating a file without a text editor.Nice Unix joke too in this case.

Page 545: Embedded Linux Course Slides

545© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Standard input

More about command input

Lots of commands, when not given input arguments, can take their input from standard input.

sortwindowslinux[Ctrl][D]linuxwindows

sort < participants.txtThe standard input of sort is taken from the given file.

sort takes its input fromthe standard input: in this case,what you type in the terminal(ended by [Ctrl][D])

Page 546: Embedded Linux Course Slides

546© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Pipes

Unix pipes are very useful to redirect the standard output of a command to the standard input of another one.

Examples

cat *.log | grep -i error | sort

grep -ri error . | grep -v “ignored” | sort -u \ > serious_errors.log

cat /home/*/homework.txt | grep mark | more

This one of the most powerful features in Unix shells!

Page 547: Embedded Linux Course Slides

547© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

The tee command

tee [-a] file

The tee command can be used to send standard output to the screen and to a file simultaneously.

make | tee build.logRuns the make command and stores its output to build.log.

make install | tee -a build.logRuns the make install command and appends its output to build.log.

Page 548: Embedded Linux Course Slides

548© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Standard error

Error messages are usually output (if the program is well written) to standard error instead of standard output.

Standard error can be redirected through 2> or 2>>

Example:cat f1 f2 nofile > newfile 2> errfile

Note: 1 is the descriptor for standard output, so 1> is equivalent to >.

Can redirect both standard output and standard error to the same file using &> :cat f1 f2 nofile &> wholefile

Page 549: Embedded Linux Course Slides

549© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Special devices (1)

Device files with a special behavior or contents

/dev/nullThe data sink! Discards all data written to this file.Useful to get rid of unwanted output, typically log information:mplayer black_adder_4th.avi &> /dev/null

/dev/zeroReads from this file always return \0 charactersUseful to create a file filled with zeros:dd if=/dev/zero of=disk.img bs=1k count=2048

See man null or man zero for details

Page 550: Embedded Linux Course Slides

550© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Special devices (2)

/dev/randomReturns random bytes when read. Mainly used by cryptographic programs. Uses interrupts from some device drivers as sources of true randomness (“entropy”).Reads can be blocked until enough entropy is gathered.

/dev/urandomFor programs for which pseudo random numbers are fine.Always generates random bytes, even if not enough entropy is available (in which case it is possible, though still difficult, to predict future byte sequences from past ones).

See man random for details.

Page 551: Embedded Linux Course Slides

551© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

AnnexesInit runlevels

Page 552: Embedded Linux Course Slides

552© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

System V init runlevels (1)

Introduced by System V UnixMuch more flexible than in BSD

Make it possible to start or stop different services for each runlevel

Correspond to the argument given to /sbin/init.

Runlevels defined in /etc/inittab.

/etc/initab excerpt:

id:5:initdefault:

# System initialization.si::sysinit:/etc/rc.d/rc.sysinit

l0:0:wait:/etc/rc.d/rc 0l1:1:wait:/etc/rc.d/rc 1l2:2:wait:/etc/rc.d/rc 2l3:3:wait:/etc/rc.d/rc 3l4:4:wait:/etc/rc.d/rc 4l5:5:wait:/etc/rc.d/rc 5l6:6:wait:/etc/rc.d/rc 6

Page 553: Embedded Linux Course Slides

553© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

System V init runlevels (2)

Standard levels

init 0Halt the system

init 1Single user mode for maintenance

init 6Reboot the system

init SSingle user mode for maintenance.Mounting only /. Often identical to 1

Customizable levels: 2, 3, 4, 5

init 3Often multi-user mode, with only command-line login

init 5Often multi-user mode, with graphical login

Page 554: Embedded Linux Course Slides

554© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

init scripts

According to /etc/inittab settings, init <n> runs:

First /etc/rc.d/rc.sysinit for all runlevels

Then scripts in /etc/rc<n>.d/

Starting services (1, 3, 5, S):runs S* scripts with the start option

Killing services (0, 6):runs K* scripts with the stop option

Scripts are run in file name lexical orderJust use ls -l to find out the order!

Page 555: Embedded Linux Course Slides

555© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

/etc/init.d

Repository for all available init scripts

/etc/rc<n>.d/ only contains links to the /etc/init.d/ scripts needed for runlevel n

/etc/rc1.d/ example (from Fedora Core 3)

K01yum -> ../init.d/yumK02cups-config-daemon -> ../init.d/cups-config-daemonK02haldaemon -> ../init.d/haldaemonK02NetworkManager ->../init.d/NetworkManagerK03messagebus -> ../init.d/messagebusK03rhnsd -> ../init.d/rhnsdK05anacron -> ../init.d/anacronK05atd -> ../init.d/atd

S00single -> ../init.d/singleS01sysstat -> ../init.d/sysstatS06cpuspeed -> ../init.d/cpuspeed

Page 556: Embedded Linux Course Slides

556© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Handling init scripts by hand

Simply call the /etc/init.d scripts!

/etc/init.d/sshd startStarting sshd: [ OK ]

/etc/init.d/nfs stopShutting down NFS mountd: [FAILED]Shutting down NFS daemon: [FAILED]Shutting down NFS quotas: [FAILED]Shutting down NFS services: [ OK ]

/etc/init.d/pcmcia statuscardmgr (pid 3721) is running...

/etc/init.d/httpd restartStopping httpd: [ OK ]Starting httpd: [ OK ]

Page 557: Embedded Linux Course Slides

557© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Embedded Linux driver development

AnnexesLinux DMA API

Page 558: Embedded Linux Course Slides

558© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

DMA situations

Synchronous

A user process calls the read method of a driver. The driver allocates a DMA buffer and asks the hardware to copy its data. The process is put in sleep mode.

The hardware copies its data and raises an interrupt at the end.

The interrupt handler gets the data from the buffer and wakes up the waiting process.

Asynchronous

The hardware sends an interrupt to announce new data.

The interrupt handler allocates a DMA buffer and tells the hardware where to transfer data.

The hardware writes the data and raises a new interrupt.

The handler releases the new data, and wakes up the needed processes.

Page 559: Embedded Linux Course Slides

559© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Memory constraints

Need to use contiguous memory in physical space

Can use any memory allocated by kmalloc (up to 128 KB) or __get_free_pages (up to 8MB)

Can use block I/O and networking buffers,designed to support DMA.

Can not use vmalloc memory(would have to setup DMA on each individual page)

Page 560: Embedded Linux Course Slides

560© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Reserving memory for DMA

To make sure you've got enough RAM for big DMA transfers...Example assuming you have 32 MB of RAM, and need 2 MB for DMA:

Boot your kernel with mem=30The kernel will just use the first 30 MB of RAM.

Driver code can now reclaim the 2 MB left:dmabuf = ioremap (

0x1e00000, /* Start: 30 MB */0x200000 /* Size: 2 MB */);

Page 561: Embedded Linux Course Slides

561© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Memory synchronization issues

Memory caching could interfere with DMA

Before DMA to device:Need to make sure that all writes to DMA buffer are committed.

After DMA from device:Before drivers read from DMA buffer, need to make sure that memory caches are flushed.

Bidirectional DMANeed to flush caches before and after the DMA transfer.

Page 562: Embedded Linux Course Slides

562© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Linux DMA API

The kernel DMA utilities can take care of:

Either allocating a buffer in a cache coherent area,

Or make sure caches are flushed when required,

Managing the DMA mappings and IOMMU (if any)

See Documentation/DMA-API.txtfor details about the Linux DMA generic API.

Most subsystems (such as PCI or USB) supply their own DMA API, derived from the generic one. May be sufficient for most needs.

Page 563: Embedded Linux Course Slides

563© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Limited DMA address range?

By default, the kernel assumes that your device can DMA to any 32 bit address. Not true for all devices!

To tell the kernel that it can only handle 24 bit addresses:if (dma_set_mask (dev, /* device structure */ 0xffffff /* 24 bits */

)) use_dma = 1; /* Able to use DMA */else use_dma = 0; /* Will have to do without DMA */

Page 564: Embedded Linux Course Slides

564© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Coherent or streaming DMA mappings

Coherent mappingsCan simultaneously be accessed by the CPU and device.So, have to be in a cache coherent memory area.Usually allocated for the whole time the module is loaded.Can be expensive to setup and use.

Streaming mappings (recommended)Set up for each transfer.Keep DMA registers free on the physical hardware registers. Some optimizations also available.

Page 565: Embedded Linux Course Slides

565© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Allocating coherent mappings

The kernel takes care of both the buffer allocation and mapping:

include <asm/dma-mapping.h>

void * /* Output: buffer address */dma_alloc_coherent(

struct device *dev, /* device structure */size_t size, /* Needed buffer size in bytes */dma_addr_t *handle, /* Output: DMA bus address */gfp_t gfp /* Standard GFP flags */

);

void dma_free_coherent(struct device *dev,size_t size, void *cpu_addr, dma_addr_t handle);

Page 566: Embedded Linux Course Slides

566© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

DMA pools (1)

dma_alloc_coherent usually allocates buffers with __get_free_pages (minimum: 1 page).

You can use DMA pools to allocate smaller coherent mappings:

<include linux/dmapool.h>

Create a dma pool:struct dma_pool *dma_pool_create (

const char *name, /* Name string */struct device *dev, /* device structure */size_t size, /* Size of pool buffers */size_t align, /* Hardware alignment (bytes) */size_t allocation /* Address boundaries not to be crossed */

);

Page 567: Embedded Linux Course Slides

567© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

DMA pools (2)

Allocate from poolvoid * dma_pool_alloc (

struct dma_pool *pool,gfp_t mem_flags,dma_addr_t *handle

);

Free buffer from poolvoid dma_pool_free (

struct dma_pool *pool,void *vaddr,dma_addr_t dma);

Destroy the pool (free all buffers first!)void dma_pool_destroy (struct dma_pool *pool);

Page 568: Embedded Linux Course Slides

568© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Setting up streaming mappings

Works on buffers already allocated by the driver

<include linux/dmapool.h>

dma_addr_t dma_map_single(struct device *, /* device structure */void *, /* input: buffer to use */size_t, /* buffer size */enum dma_data_direction /* Either DMA_BIDIRECTIONAL,

DMA_TO_DEVICE or DMA_FROM_DEVICE */);

void dma_unmap_single(struct device *dev, dma_addr_t handle, size_t size, enum dma_data_direction dir);

Page 569: Embedded Linux Course Slides

569© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

DMA streaming mapping notes

When the mapping is active: only the device should access the buffer (potential cache issues otherwise).

The CPU can access the buffer only after unmapping!

Another reason: if required, this API can create an intermediate bounce buffer (used if the given buffer is not usable for DMA).

Possible for the CPU to access the buffer without unmapping it, using the dma_sync_single_for_cpu() (ownership to cpu) and dma_sync_single_for_device() functions (ownership back to device).

The Linux API also support scatter / gather DMA streaming mappings.

Page 570: Embedded Linux Course Slides

570© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Lab Information

Login:

root:secret and gby:qwerty

Running the Eclipse IDE:

/opt/course/scripts/eclipse &

Running the QEMU Emulator:

/opt/course/scripts/run-qemu &

The emulated board files are at:

/opt/course/emulation/root

The kernel module template is at:

/opt/course/skeleton/

Page 571: Embedded Linux Course Slides

571© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd.

For full copyright information see last page.Creative Commons Attribution-ShareAlike 2.0 license

Copyrights

© Copyright 2006-2004, Michael Opdenacker© Copyright 2003-2006, Oron Peled© Copyright 2004-2006 Codefidence Ltd. Portions of this text are reprinted and reproduced in electronic form from IEEE Std 1003.1, 2003 Edition, Standard for Information Technology -- Portable Operating System Interface (POSIX), The Open Group Base Specifications Issue 6, Copyright (C) 2001-2003 by the Institute of Electrical and Electronics Engineers, Inc and The Open Group. In the event of any discrepancy between this version and the original IEEE and The Open Group Standard, the original IEEE and The Open Group Standard is the referee document. The original Standard can be obtained online at http://www.opengroup.org/unix/online.html .Portions © Xavier Leroy <[email protected]> Tux Image Copyright: (C) 1996 Larry EwingLinux is a registered trademark of Linus Torvalds.All other trademarks are property of their respective owners.Used and distributed under a Creative Commons Attribution-ShareAlike 2.0 license