linux device driver sum up
TRANSCRIPT
-
8/9/2019 Linux Device Driver Sum Up
1/53
1. Nhung van de can hoc
Kernel Space Timer Services
Timer Interrupts - HZ and jiffi es
Delaying Execution
Using Task Queues
Kernel Space Timers
Interrupt Handling
Linux and Interrupts
IRQ Action Table
Register, Enabling and Disabling Interrupts
Minimizing Interrupt Latency
2. Explain the differences between user memory and kernel memory
The cs register has one important function: it includes a 2bit fieldthat specifies the Current Privilege Level (CPL) of the CPU.
The value 0 denotes the highest privilege leve l, while the value
3 denotes the lowest one.
Linux uses only levels 0 and 3 , which are respectively called Kernel
Mode and User Mode.
A similar situation occurs for the ss register: it must refer to
a User Mode stack inside the user data segment when the CPL is 3,
and it must refer to a Kernel Mode stack inside the kernel data
segment when the CPL is 0. When switching from User Mode to KernelMode.
A process can run in two modes:1.user mode 2.kernel mode
User Mode(Space)
A mode of the CPU when running a pr ogram.
In this mode ,the user process has no access to the memory
locations used by the kernel.
When a program is running in User Mode, it cannot directly access
the kernel data structures or the kernel programs.
Kernel Mode A mode of the CPU when running a program
In this mode, it is the kernel that is running on behalf of the
user process and directly access the kernel data structures or
the kernel programs.
Once the system call returns,the CPU switches back to user mode.
-
8/9/2019 Linux Device Driver Sum Up
2/53
It provides the main functions of the abstract machine (system
calls and Interrupt and traps).
user and kernel mode : When you execute a C program,the CPU runs in user mode till the
system call is invoked
In this mode,the user process has access to a limited section
of the computer's memory and can execute a restricted set of
machine instructions.
However,when the process invokes a system call,the CPU switches
from user mode to a more privileged mode - kernel mode
In this mode ,it is the kernel that runs on behalf of the user
process,but it has access to any memory location and can executeany machine instruction.
After the system call has returned,the CPU switches back to user
mode
User/Kernel Interactions
Transfer of Control between User and Kernel Mode
System Calls
Interrupts (timer or device)
Transfer of Data between User and Kernel Space
Memory copy /proc/ file system
Approximate structure of generic UNIX kernel
3. Explain the differences between user memory and kernel memory
The kernel offers several subroutines or functions in user space, which allow the
end-user application programmer to interact with the hardware.
-
8/9/2019 Linux Device Driver Sum Up
3/53
Usually, in UNIX or Linux systems, this dialogue is performed through functions or
subroutines in order to read and write files. The reason for this is that in Unix devices
are seen, from the point of view of the user, as files.
Linux and Unix use the file which is a well understood data structure
for handling byte sequences to represent I/O device s.
A device driver consists of a set of routines that control a
peripheral device attached to a workstation
On the other hand, in kernel space Linux also offers several functions or subroutines to
perform the low level interactions directly with the hardware, and allow the transfer of
information from kernel to user space.
Usually, for each function in user space (allowing the use of devices or files), there
exists an equivalent in kernel space (allowing the transfer of information from the
kernel to the user and vice-versa).
4. List the major subsystems of the Linux kernel
-
8/9/2019 Linux Device Driver Sum Up
4/53
Kernel subsystems
Process management
The kernel is in charge of creating and destroying processesandhandling their connection to the outside world (input and
output). Communication among different processes (through
signals, pipes, or interprocesscommunication primitives) is
basic to the overall system functionality and is also handled
by the kernel. In addition, the scheduler, which controls how
-
8/9/2019 Linux Device Driver Sum Up
5/53
processes share the CPU, is part of process management. More
generally, the kernel's process management activity implements
the abstraction of several processes on top of a single CPU or
a f e w o f t h e m .
Process Management(PM): The Process Management system controls
the creation, termination, accounting, and scheduling of
processes. It also facilitates and manages the complex task of
the creation of child processes.
Memory management
The computer's memory is a major resource, and the policy used
to deal with it is a critical one for system performance. The
kernel builds up a virtual addressing space for any and allprocesses on top of the limited available resources. The
d i f f e r e n t p a r t s o f t h e k e r n e l i n t e r a c t w i t h t h e
memory-management subsystem through a set of function calls,
ranging from the simple malloc/free pair to much more exotic
f u n c t i o n a l i t i e s .
File systems
Unix is heavily based on the filesystem concept; almost
everything in Unix can be treated as a file. The kernel builds
a structured filesystem on top of unstructured hardware, andthe resulting file abstraction is heavily used throughout the
whole system. In addition, Linux supports multiple filesystem
types, that is, different ways of organizing d ata on the physical
medium.For example, diskettes may be formatted with either the
Linuxstandard ext2 filesystem or with the commonly used FAT
filesystem.
Device control
Almost every system operation eventually maps to a physical
device. With the excepti on of the processor, memory, and a veryfew other entities, any and all device control operations are
performed by code that is specific to the device being addressed.
That code is called a device driver. The kernel must have
embedded in it a device driver for every peripheral present on
a system, from the hard drive to the keyboard and the tape
-
8/9/2019 Linux Device Driver Sum Up
6/53
streamer. This aspect of the kernel's functions is our primary
interest in this book.
A set of routines needed to operate a specific device is known
as device driver. They hide completely the details of how the
device works.
Networking
Networking must be managed by the operating system because most
network operations are not specific to a process: incoming
packets are asynchronous events. The packets must be collected,
identified, and dispatched before a process takes care of them.
The system is in charge of delivering data packets across program
and network interfaces, and it must control the execution ofprograms according to their network activity. Addition ally, all
the routing and address resolution issues are implemented within
the kernel
networking in the Linux kernel is implemented by three
layers of software:
The socket interface
Protocol drivers
Network device drivers
Any network interconnection is made through the interface(device), that is able to exchange data with other hosts.
Transactions made using an Interface
Interface can be hardware or software
Interface is incharge of sending and receiving data
packets
-
8/9/2019 Linux Device Driver Sum Up
7/53
Network Interface isnt easily mapped to a node in the
filesystem
Though UNIX will map it as eth0
I/O Software Layers
Chu y: Kernel features
One of the good features of Linux is the ability to extend at
runtime the set of features offered by the kernel. This means
that you can add functionality to the kernel while the system
is up and running. Each piece of code that can be added to the
kernel at runtime is called a module. The Linux kernel offers
support for quite a few different types (or classes) of modules,including, but not limited to, device drivers. Each module is
made up of object code (not linked into a complete executable)
that can be dynamically linked to the running kernel by the
insmod program and can be unlinked by the rmmod program.
Devices and Modules
Adriver is the part of the OS that manages communication with devices;
thus, they are usually calleddevicedrivers.
-
8/9/2019 Linux Device Driver Sum Up
8/53
Differences between software and hardware are clearly specified in
this scheme. At the left side, user programs may interact with the
devices (for example, a hard disk) through a set ofhigh-levellibraryfunctions. For example, we can open and write to a file of the hard disk
calling the Clibrary functions fopen, fprintf and close:
FILE *fid=fopen("filename", "w");
fprintf(fid, "Hello, world!");
fclose(fid);
The user can also write to a file (or to another device such as a printer)
from the OS shell, using commands such as:
echo "Hello, world!" >
echo "Hello, world!" > /dev/lpTo execute this command, both the shell and the library functions
perform a call to a low level function of the OS, e.g., open(), write() or
close():
fid = open("/dev/lp", O_WRONLY);
write(fid, "Hello, world!");
close(fid);
Each device can be referred to as a special file named /dev/*. Internally,
the OS is composed of a set of drivers, which are pieces of software
that perform the low-level communication with each device. At thisexecute level, the kernel calls driver functions such as lp_open() or
lp_write().
Finally, the device driver is the physical interface between the
software and the hardware. The driver reads from and writes to the
hardware through ports (memory addresses where the hardware links
-
8/9/2019 Linux Device Driver Sum Up
9/53
physically), using the internal functions
out_p(0x3a, 0x1f);
data = in_p(0x3b);
Note that these functions are not available to the user .
Since the Linux kernel runs in protected mode, the low
memory addresses , where the ports addresses reside, are not
user accessible.
The Unix way of looking at devices distinguishes between three
device types. Each module usually implements one of these types,
and thus is classifiable as a char module, a block module, or
a network module.
Characterdriverstransmitinformation from theuserto thedevice(orviceversa) byteperbyte
Two examplesaretheprinter, /dev/lp, andthememory (yes, the
memory isalso adevice), /dev/mem
Blockdrivers(seeFigure3) transmit information blockperblock. This
meansthat theincoming data (from theuserorfrom thedevice) are
storedin a bufferuntilthebufferisfull. When thisoccurs, thebuffer
content isphysically sent to thedeviceorto theuser.
Theclearest examplesof thistypeofdriveraredisks: floppy disks
(/dev/fd0), IDE harddisks(/dev/hda) andSCSI harddisks(/dev/sd1)
Streamsaretheyoungestdrivers(seeFigure5) and aredesigned for
-
8/9/2019 Linux Device Driver Sum Up
10/53
very high speed data flows. Both the kernel and the driver include
severalprotocollayers. The best example of this type is a network
driver
Terminaldrivers(seeFigure4) constituteaspecialset of character
driversforusercommunication. Forexample, commandtoolsinan
open windowsenvironment, anX terminalora console, aredeviceswhich requirespecial functions, e.g., theupanddownarrowsfora
commandbuffermanagerortabbing in thebash shell. Examplesof
block driversare/dev/tty0 or/dev/ttya (aserialport). In both casesthe
kernelincludesspecialroutines, andthedriverspecialprocedures, to
copewith allparticularfeatures.
Userlevel programs communicate with the kernel using system calls,
for instance, open(), read(), write(), ioctl(), close() , and the
like.
-
8/9/2019 Linux Device Driver Sum Up
11/53
-
8/9/2019 Linux Device Driver Sum Up
12/53
5. Explain how Linux implements file and device Input/Output (I/O) operations
I/O Architecture
The 80 x 86 microprocessors use 16 of their address pins to address I/O devices and 8, 16, or 32 of
their data pins to transfer data.
The data path that connects a CPU to an I/O device is generically called an I/O bus.
The I/O bus, in turn, is connected to each I/O device by means of a hierarchy of hardware components
including up to three elements: I/O ports , interfaces, and device controllers
I/O Ports
Each device connected to the I/O bus has its own set of I/O addresses, which are usually called
I/O ports .
In the IBM PC architecture, the I/O address space provides up to 65,536 8-bit I/O ports.
-
8/9/2019 Linux Device Driver Sum Up
13/53
Four special assembly language instructions called in, ins , out , and outs allow the CPU to read
from and write into an I/O port. While executing one of these instructions, the CPU selects the
required I/O port and transfers the data between a CPU register and the port.
I/O ports may also be mapped into addresses of the physical address space
The CPU writes the commands to be sent to the device into the device control registerand reads
a value that represents the internal state of the device from the device status register.
The CPU also fetches data from the device by reading bytes from the device input registerand
pushes data to the device by writing bytes into the device output register.
Accessing I/O ports
The in, out, ins, and outs assembly language instructions access I/O ports. The following
auxiliary functions are included in the kernel to simplify such accesses: The suffix "b," "w,"
or "l" refers, respectively, to a byte (8 bits), a word (16 bits), and a long (32 bits).
inb( ), inw( ), inl( )
inb_p( ), inw_p( ), inl_p( ) outb( ), outw( ), outl( )
outb_p( ), outw_p( ), outl_p( )
insb( ), insw( ), insl( )
outsb( ), outsw( ), outsl( )
I/O Interfaces
An I/O interface is a hardware circuit inserted between a group of I/O ports and the
corresponding device controller. It acts as an interpreter that translates the values in the I/O ports
into commands and data for the device.
In the opposite direction, it detects changes in the device state and correspondingly updates the
I/O port that plays the role of status register.
This circuit can also be connected through an IRQ line to a Programmable Interrupt Controller, so
that it issues interrupt requests on behalf of the device
There are two types of interfaces:
Custom I/O interfaces
-
8/9/2019 Linux Device Driver Sum Up
14/53
Keyboard interface
Graphic interface
Disk interface
Bus mouse interface
Network interface
General-purpose I/O interfaces
Parallel port
Serial port
PCMCIA interface
SCSI (SmallComputerSystem Interface) interface
Universal serial bus (USB)
Device Controllers
It interprets the high-level commands received from the I/O interface and forces the device to
execute specific actions by sending proper sequences of electrical signals to it.
It converts and properly interprets the electrical signals received from the device and modifies
(through the I/O interface) the value of the status register.
6. Device Files
Major number, identifies the device type. Traditionally, all device files that have the same major number and
the same type share the same set of file operations, because they are handled by the same device driver.
minor number, identifies a specific device among a group of devices that share the same major number.
For instance, a group of disks managed by the same disk controller have the same major number and
different minor numbers .
the major and minor numbers of the device files are 8 bits long. Thus, there could be at most 65,536 block
device files and 65,536 character device files. You might expect they will suffice, but unfortunately they don't.
Major device numbers are used by the Linux system to map I/O requests
to the driver code, thereby deciding which devic e driver to execute,
when a user reads from or writes to the special file.
The minor numbers are entirely under the control of the driver
writer, and usually refer to ysubdevicesy of the device. Tuc la co
nhieu thiet bi thuoc cung 1 chung? Loai,dung minor number de phanbiet cac thiet bi do voi nhau chang han nhu hard disk
The mknod( ) system call is used to create device files. It receives the name of the device file, its type, and
the major and minor numbers as its parameters. Device files are usually included in the/devdirectory. Notice
that character and block devices have independent numbering, so block device (3,0) is different from
character device (3,0).
-
8/9/2019 Linux Device Driver Sum Up
15/53
a device file is not associated with any real hardware device, but represents a fictit ious logical device. device.
For instance, /dev/null is a device file corresponding to a "black hole;" all data written into it is simply
discarded, and the file always appears empty
CHU Y rang: ten thiet bi thuc ra khogn quan trong doi voi 1 so application programs vi chi can 3 tham so :
kieu thiet bi, major number va minor number la xac dinh duco thiet bi, ten thiet bi ko quan trong. Tuy nhien doi
voi 1 so application programs thi lai giao tiep thong qua ten thiet bi ao
As far as the kernel is concerned, the name of the device file is irrelevant
If you create a device fil e named/tmp/diskof type "block" with the major number 3 and minor number 0,
it would be equivalent to the/dev/hda device file shown in the table.
On the other hand, device filenames may be significant for some application programs
7. Assigning Device Numbers
There are essentially two methods for assigning a range of device numbers to a character device driver. The first method, which should be used for all new device drivers, relies on the
register_chrdev_region( ) and alloc_chrdev_region( ) functions, and assigns an arbitrary range of
device numbers. For instance, to get an interval of numbers starting from the dev_t value dev and of
size size:
register_chrdev_region(dev, size, "foo");
-
8/9/2019 Linux Device Driver Sum Up
16/53
These functions do not execute cdev_add( ), so the device driver must execute cdev_add( ) after the
requested interval has been successfully assigned.
The second method makes use of the register_chrdev( ) function and assigns a fixed interval of device
numbers including a single major number and minor numbers from 0 to 255. In this case, the device
driver must not invoke cdev_add( ).
The register_chrdev( ) function is used by drivers that require an old-style interval of device
numbers: a single major number and minor numbers ranging from 0 to 255.
The function receives as its parameters the requested major number major (zero for dynamic
allocation), the name of the device driver name, and a pointer fops to a table of file operations
specific to the character device files in the interval.
8. Use the printk( ) function to print messages from within the Linux kernel
printk(): A version of printf() for the kernel.
9. Linux System Calls
The kernel is not a separate task under Linux. It is as if each
process has a copy of the kernel . When a user process executes a
system call, it does not transfer control to another process, but
changes its execution mode from user to kernel mode.
In kernel mode, while executing the system call, the process has
access to the kernel address space, and through supporting
functions , it has access to the address space of the user executing
the call.
Device Driver Development Supporting Functions
The table below contains most of the common supp orting functions
available for writing device drivers.
add_timer()
cli()
end_request()
free_irq()
get_fs*(): Allows a driver to access data in user space, a memory
area distinct from the kernel inb(), inb_p():Reads a byte from a port. Here, inb() goes as fast
as it can, while inb_p() pauses before returning.
irqaction()
IS_*(inode)
kfree*(): Frees memory previously allocated with kmalloc()
-
8/9/2019 Linux Device Driver Sum Up
17/53
kmalloc():Allocates a chu nk of memory no larger than 4096 bytes.
MAJOR():Reports the major device number for a device.
MINOR():Reports the minor device number for a device.
memcpy_*fs():Copies chunks of memory between user space and
kernel space
outb(), outb_p() :Writes a byte to a port. Here, outb() goes as
fast as it can, while outb_p() pauses before returning.
printk():A version of printf() for the kernel.
put_fs*(): Allows a driver to write data in user space.
register_*dev() :Registers a device with the kernel.
request_irq():Requests an IRQ from the kernel, and, if
successful, installs an IRQ interrupt handler.
A device driver provides the I/O system with a standard interfaceto the hardware, hiding the unique characteristics of the hardware
device from the user to the greatest extent possible.
illustrates a user program that employs some basic system calls to
read characters from a device into a buffer. When a system call is
requested, the kernel transfers control to the appropriate device
driver routine that executes on behalf of the calling user process flow of execution of a system call within th e Linux operating system
-
8/9/2019 Linux Device Driver Sum Up
18/53
major subsystem oflinux kernel
-
8/9/2019 Linux Device Driver Sum Up
19/53
System Call Interface(SCI)
Asystem call is an interface between a user-space application and a service
that the kernelprovides. Because the service is provided in the kernel, a
direct call cannot be performed; instead, you must use a process of crossingthe user-space/kernel boundary.
A system call is the method that the user process uses to ask for
an action from the O.S.
The SCI is a thin layer that provides the means to perform
function calls from user space into the kernel.
A system call is an interface between a user s spaceapplication
and a service that the kernelprovides.
To access the services available in the operating system, all
Unix/Linux system offer around 200 special functions calledsystem calls.
System calls provide a layer between the hardware and userspace
processes.This layer serves three primary purposes : First, it provides an abstracted hardware interface for
userspace.When reading or writing from a file, for example,
applications need not concern themselves with the type of
disk, media, or even the filesystem on which the file resides
Second, system calls ensure system se and stability.For
example, this prevents applications from incorrectly usinghardware, stealing o ther processes' resources, or doing harm
to the system.
A system call is nothing but a routine built into the
kernel and performs a very basic function that requires
communication with the CPU , memory,and devices.
All activities related to file handling, process and
memory management and maintenance of the user are handled
by the kernel using these system calls.
Finally, a single common layer between user space and therest of the system allows for the virtualized system provided
to processes.If applications were free to access systemresources without the kernel's knowledge, it would be nearly
impossible to implement multitasking and virtual memor y, and
certainly impossible to do so with stability and security.
-
8/9/2019 Linux Device Driver Sum Up
20/53
user and kernel mode :
When you execute a C program,the CPU runs in user mode till
the system call is invoked
In this mode,the user process has access to a limited sectionof the computer's memory and can execute a restricted set
of machine instructions.
However,when the process invokes a system call,the CPU
switches from user mode to a more privileged mode - kernel
mode
In this mode ,it is the kernel that runs on behalf of the
user process,but it has access to any memory location and
can execute any machine instruction.
After the system call has returned,the CPU switches back touser mode
System call and Library Function call
If you are a C programmer on GNU/Linux and have not used
system calls,then you must have used the library functions
A set of functions available in the standard library that
is shipped with the C compiler for Linux and nonLinux system
Nhu vay chung tat hay rang co 2 cach de lam: hoac la tu tao
ra cac system call hoac la su dung thu vien libraries. Hay noi
cach khac thu vien nay da xay dung cho ta san cac system call
va chung ta chi viec sudung chang han nhu sau:
For example, we can open and write to a file of the hard disk calling
the Clibrary functions fopen, fprintf and close:FILE *fid=fopen("filename", "w");
fprintf(fid, "Hello, world!");
fclose(fid);
On Linux systems ,these library functions are built on top
of the system calls.
-
8/9/2019 Linux Device Driver Sum Up
21/53
system call is built into the kernel.
The standard C library offers separate functions to read a
block of data(fread),and a line(fgets),and a single
character(fgetc). All these functions ultima tely invoke the only system call
available for reading input read.
using system call is usually the most efficient way to
perform I/O operations and is some time more convenient ,too.
For example: fopen can create a file in read or write mode
but can't set the file permissions(in chmod style)which open
does easily.
A library function can't tell you the size of a file which
the stat system call does by looking up a structureassociated with the inode.
when a program makes system calls ,the arguments are packaged
up and handed to the kernel ,which takes over execution of
the program untill the call completes
API System Call OS Relationship
Standard CLibrary Example
-
8/9/2019 Linux Device Driver Sum Up
22/53
System CallParameter Passing
Three general methods used to pass parameters to the OS
Simplest: pass the parameters in registers. In some
cases, may be more parameters than registers Parameters stored in a block, or table, in memory, and
address of blockpassed as a parameter in a register . This
approach taken by Linux and Solaris
Parameters placed, or pushed, onto the stack by the
program and popped off the stackby the operating system
Block and stack methods do not limit the number or
length ofparameters being passed
Parameter Passing via Table
-
8/9/2019 Linux Device Driver Sum Up
23/53
10.Introducing LKMprogramming There are several kernel architectures, but the two most important are:
Monolithic
Micro-kernell
Monolithicn kernel
The monolithic term means that the kernel is implemented as an only one
process, with an only address space. It is like when you create a single .c file,
and it is executed as a single process. People that are in favour of this model,
cite the simplicity as the main goal. With a monolithic kernel, communication
is simple, and it is possible to call a defined function from wherever in thekernel. Most of the UNIX kernels are monolithic (Hurd is an exception)
Micro-kernel
The approach for micro-kernel design is simple: Let the kernelperform only theessential operations. Everything else that can be performed in user space
should be done there. In a micro-kernel scenario, the kernel must communicate
with the other operating system parts. Typically, the memory management, file
systems and IPC communications are not inside the kernel. This model can
take advantage of memory protection features provided by modern processors.
-
8/9/2019 Linux Device Driver Sum Up
24/53
The drawback is the extra communication caused by this distributed schema
where every subsystem has it's own address space.
Linux kernel is Monolithic, but it is also modular, i.e. the kernel can
dynamically load parts of the kernel code. This is a really nice feature since in
this way, it is possible to extend the kernel capabilities without modifying the
rest of the code. With traditional UNIX kernels, it was necessary to recompile
the kernel to add a new feature. Now, it is possible to insert the module while
the kernel is running. This doesn't produce any problem. Modern UNIX kernels
support modules loading.
Linux kernel module:
a kernel module is a part of the kernel code. In fact, if you have evercompiled your kernel, surely you know this: when we set preferences for
our customized kernel, we can choose a feature to be compiled as a module
or to be integrated in the kernel code.
Almost everything in kernel code can be implemented as a module.
However, it is common to implement file systems, drivers or some
programs that need kernel mode (e.g. performance analysers like vtune)
if your program needs to work in kernel mode, the best you can do is to
implement it as a module instead of modifying the rest of the kernel.
structure of a kernel module
-
8/9/2019 Linux Device Driver Sum Up
25/53
11.Kernel command using Linux system calls
Trong he dieu hanh linux chung ta co 2 che do la user mode va kernel mode.
User mode is non-privileged in that processes in this mode are not allowed
to access those portions ofmemory that have been allocated to the kernelor to other programs.
The kernel is a program that constitutes the core of an operating system,
and it has complete control over all resources on the system and
everything that occurs on it.
When a usermode process(i.e., a processcurrently in usermode) wantsto
utilize a service providedby the kernel (i.e., accesssystemresourcesother
than the limitedmemory space that is allocated to the user program), it
must switch temporarily into kernelmode, also called system mode, by
meansof a systemcall. Kernel mode has root (i.e., administrative) privileges, including root access
permissions (i.e., permission to access any memory space or other
resources on the system). This allows the operating system to perform
restricted actions such as accessing hardware devices or the memory
management unit (MMU). When the kernel has satisfied the request made
by a process, it restores that process to user mode
Chu y rang: chung ta co 2 cach de co the su dung cac dich vu cua kernel thong
qua system call hoac la thogn qua viec doc file /proc filesystem
Access the linux kernel using the /proc filesystem The /proc filesystem is a virtual filesystem that permits a novel approach
for communication between the Linux kernel and user space.
the content of these virtual files is dynamically created.
The /proc filesystem contains directories (as a way of organizing
information) and virtual files . Avirtual file can present information from
-
8/9/2019 Linux Device Driver Sum Up
26/53
the kernel to the user and also serve as a means of sending information
from the user to the kernel.
System call:
Asystem call is used by application (user) programs to request service fromthe operating system.
An operating system can access a system's hardware directly, but a
user program is not given direct access to the hardware. This is done so
that the kernel can keep the system safe and secure from malicious
user programs.
But often, a user program requires some information from the
hardware (e.g., from a web camera to show you the picture), but it
cannot get the information directly. So, it requests the operating
system to supply it the information. This request is made by using anappropriate system call.
System calls can be classified into six groups
process management
interprocess communication,
memory management
file system
initialization and other.
The kernel maintains a list of all registered system calls in the system call
table. This table assigns each valid system call a unique system callnumber which cannot be changed or recycled. Processes do not refer to
system calls by name, but rather by their system call number.
There are 294 syscalls defined in a 2.6 linux kernel (#define NR_syscalls
294). You can see the list at unistd.h file.
Asystem call executes in the kernel mode.
Every system call has a number associated with it. This number is
passed to the kernel and that's how the kernel knows which system
call was made.
When a user program issues a system call, it is actually calling alibraryroutine.
The library routine issues a trap to the Linux operating system by
executing INT0x80assembly instruction.
It also passes the system call number to the kernel using the EAX
register.
-
8/9/2019 Linux Device Driver Sum Up
27/53
The arguments of the system call are also passed to the kernel using
other registers (EBX, ECX, etc.).
The kernel executes the system call and returns the result to the user
program using a register. If the system call needs to supply the userprogram with large amounts of data, it will use another mechanism
(e.g., copy_to_user call).
System calls: mechanism
A process is able to use services provided by the kernel by making a
system call [2].Every system call has a specific number.This number iswritten into the EAX register. There can be up to 6 parameters, which are
set into the registers EBX, ECX, EDX, EDI, ESI and EBP. If a system call
needs more than 6 values to pass, it has to use pointers to structures,
where the additionalparameters are stored.
To switch to kernel mode the software interrupt 0x80 is called and the
-
8/9/2019 Linux Device Driver Sum Up
28/53
system call handler calls the system call services routine according to the
system call number found in the EAX register. The address of every
system call service routine is stored in the system call table. The system
calls return value is stored in the EAX register.
Each system call is multiplexed into the kernel through a single entry
point. The eax register is used to identify the particular system call that
should be invoked, which is specified in the Clibrary (per the call from the
user-space application). When the C library has loaded the system call
index and any arguments, a software interrupt is invoked (interrupt 0x80),
which results in execution (through the interrupt handler) of the
system_call function. This function handles all system calls, as identified
by the contents of eax. After a few simple tests, the actual system call is
invoked using the system_call_table and index contained in eax. Upon
return from the system call, syscall_exit is eventually reached, and a
call to resume_userspace transitions back to user-space. Execution
resumes in the Clibrary, which then returns to the user application.
This table, shown in Figure 2, uses the indexprovided in eax to identify
which system call to invoke from the table (sys_call_table )
-
8/9/2019 Linux Device Driver Sum Up
29/53
List of files to be modified or created
Kernel files to be modified are listed below:
/usr/src/linux/arch/i386/kernel/syscall_table.S Add an entry to system call
dispatch table
/usr/src/linux/include/asm-i386/unistd.h Include a macro definition for
NR_XYZThis file contains the system call number that is passed to the
kernel through the register (EAX) when a system call is invoked.
/usr/src/linux/include/linux/syscalls.h This file contain the declarations for
system calls. /usr/src/linux/Makefile
New kernel files/directories to be created are listed below:
/usr/src/linux/mycall - Directory that will contain the source file, header file
and the Makefile for our system call (You can also implement your system
call in an existing file).
/usr/src/linux/mycall/mycall.c - Source file containing our system call code.
Write the corresponding service routine in kernesource tree (e.g., sys_XYZ())
CHUY cai ham nay duoc goi la Service Routine /usr/src/linux/mycall/Makefile Makefile
New user space files, to be created, to test our system call are listed below:
testmycall.c Source file that will call our system call.
testmycall.h - Header file.
-
8/9/2019 Linux Device Driver Sum Up
30/53
/usr/src/linux/arch/i386/kernel/syscall_table.S
Add a line to the end of this file (Let's assume that the name of our system
call is mycall).
Add ".long sys_mycall" at the end of the list.
/usr/src/linux/include/asm-i386/unistd.h
This file contains the system call number that is passed to the kernel
through the register (EAX) when a system call is invoked.
Muc dich: ta khai bao so hieu number cho system call ma chung ta tao ra
Add "#define __NR_mycall " at the end of the
-
8/9/2019 Linux Device Driver Sum Up
31/53
list.
If the last system call defined here is:
"#define __NR_vmsplice316", then add:
"#define __NR_mycall317" at the end of the list.
Increment the "NR_syscalls" by 1. So, if NR_syscalls is defined as:
"#define NR_syscalls 317", then change it to:
"#define NR_syscalls 318"
/usr/src/linux/include/linux/syscalls.h
This file contain the declarations for system calls.
Add the following line at the end of the file:
"asmlinkage long sys_mycall(int i);"
Nhu vay rang khi mycall() duoc goi thi no se goi den ham duoc khai bao
nhu o tren va duoi hinh sau
/usr/src/linux/Makefile
Add mycall/ to core-y (Search for regex: core-y.*+=). You will be creating
this directory. This directory will contain the source file, header file andthe Makefile for our system call.
/usr/src/linux/mycall (new kernel files/directories to be created)
Create a new directory in /usr/src/linux and name it "mycall"
/usr/src/linux/mycall/mycall.c
Create a source file named "mycall.c" in dir "mycall". mycall.c will have the
-
8/9/2019 Linux Device Driver Sum Up
32/53
code for our system call. The definition of the system call in the source file
would be asmlinkage long sys_mycall(...){...} . It should include the file
linux/linkage.h So, the file "mycall.c" willlook like:
Hoac chang han chung ta viet nhu sau:
Asmlinkage is used to look for the arguments on the kernel stack.
Reading and writing user memory
The Linux kernelprovides several functions that you can use to move
system call arguments to and from user-space. Options include simple
functions for basic types (such as get_user or put_user). For movingblocks of data such as structures or arrays, you can use another set of
functions: copy_from_user and copy_to_user . Moving
null-terminated strings have their own calls: strncpy_from_user
and strlen_from_user . You can also test whether a user-space
pointer is valid through a call to access_ok. These functions are
-
8/9/2019 Linux Device Driver Sum Up
33/53
defined in linux/include/asm/uaccess.h
Moving simple types between the kernel and user-space (such as ints
or longs) is accomplished easily with get_user and put_user. These
macros each take a value and a pointer to a variable. The get_user
function moves the value that the user-space address specifies (ptr)
into the kernel variable specified (var). The put_user function moves
the value that the kernel variable (var) specifies into the user-space
address (ptr). The functions return zero on success:
To move larger objects, such as structures or arrays, you can use the
copy_from_user and copy_to_user functions. These functions move
an entire block of data between user-space and the kernel. The
copy_from_user function moves a block of data from user-space into
kernel-space, and copy_to_user moves a block of data from the
kernel into user-space:
Finally, you can copy a NULL-terminated string from user-space to
the kernel by using the strncpy_from_user function. Before calling
this function, you can get the size of the user-space string with a call to
the strlen_user macro:
These functions provide the basics for memory movement between the
kernel and user-space. Some additional functions exist (such as those
that reduce the amount of checking performed). You can find these
functions in uaccess.h.
/usr/src/linux/mycall/Makefile
The Makefile in dir "mycall" will have only one line:
testmycall.h (new user space header file to be created) new user space files, to
-
8/9/2019 Linux Device Driver Sum Up
34/53
be created, to test our system call
Create a header file called testmycall.h. This header file should be
included by any program calling our system call.
Add three lines to it
Line 1: This is needed because we need the definition of_syscall1.
#include
Line 2: This is needed because we need the number of our system ca ll
#define __NR_mycall 317
Line 3: This is needed for system calls with 1 argument. It is explained
in detail below.
_syscall1(long, mycall, int, i)
So, our user header file looks like:
The syscall0 macro takes two arguments. The first specifies the type of
the value returned by the system call; the second argument is the name of the system
call. The name is used to identify the system call number that is stored in the
hardware register before the trap instruction is executed.
Ifyour system call requires arguments, then a different macro (such as syscall0,
where the suffix indicates the number of arguments) could be used to instantiate the
assembly code required for performing the system call.
The traditional method requires that you create function calls that match
those in the kernel in terms of system call index (so that you're calling the
right kernel service) and that the arguments match. Linuxprovides a set
of macros to provide this capability. The _syscallN macros are defined in/usr/include/linux/unistd.h and have the following format:
-
8/9/2019 Linux Device Driver Sum Up
35/53
testmycall.c (new user space source file to be created)
Create a C file called testmycall.c in the same directory as testmycall.h. The C
file willlook like:
Return Value:Long integer (in 32-bit architecture) (unsigned long)0(unsigned long)(-126):System call succeeded
(unsigned long)(-125)(unsigned long)(-1)
System call failed
Set errno.
CHU Y: khi lap trinh chung ta co the su dung cac loai cau lenh sau:get_user(), put_user(),copy_from_user(), copy_to_user(), ...
12.Virtual File system Switch (VFS)
The principal interface between a device driver and t he rest of the
Linux kernel comprises a set of standard entry points and driver
specific data structures
-
8/9/2019 Linux Device Driver Sum Up
36/53
Listing 2 illustrates how the entry points are registered with the
Virtual File system Switch using the file_operations structure.
This structure, which is defined in /usr/include/linux/fs.h ,
constitutes a list of the functions written for the driver. The
initialization routine, xxx_init()registers the file_operationsstructure with the VFS and allocates a major number for the device.
Name space
The name of the driver should be a short string. Throughout this
article we have used "xxx" as our device name.
For instance, the parallel (printer) device is the `lp'' device,
the floppies are the `fd'' devices, and the SCSI disk s are the
``sd'' devices.
To avoid name space confusion, the entry point names are formedby concatenating this unique driver prefix with a generic name
that describes the routine.For instance, xxx_open() is the
``open'' routine for the ``xxx'' driver.
13.Driver implementation in Linux
Writing LinuxDevice Driver Header files
-
8/9/2019 Linux Device Driver Sum Up
37/53
#include
Writing LinuxDevice Driver #include
#include
#include #include
#include
#include
Writing LinuxDevice Driver Initialize register (clear)
static int test_open(struct inode *inodePtr, struct file *fp)
{
printk( "Enter open routine.n" );
return 0;
}static int test_release(struct inode *inodePtr, struct file *fp)
{
MOD_DEC_USE_COUNT;
printk( "Enter test_releasen" );
return 0;
}
Writing LinuxDevice Driver Operation
static ssize_t test_read(struct file *fp, char *buf, size_t len, loff_t *offset){
printk( "Enter test_readn" );
return len;
}
static ssize_t test_write(struct file *fp, char *buf, size_t len, loff_t *offset)
{
printk( "Enter test_writen" );
return len;
}
Writing LinuxDevice Driver Mapping
struct file_operations test_fops =
{
read: test_read,
-
8/9/2019 Linux Device Driver Sum Up
38/53
write: test_write,
open: test_open,
release: test_release,
ioctl: test_ioctl,};
Writing LinuxDevice Driver
static int test_ioctl(struct inode *inodePtr, struct file *fp, unsigned int cmd,
unsigned long arg)
{
switch( cmd ){
default:
break;
}return 0;
}
Writing LinuxDevice Driver Entry point V.S. Exit point
int test_init_module(void)
{
register_chrdev( 100, testName, &test_fops );
printk( "Init test modulen" );
return 0;}
void test_cleanup_module(void)
{
unregister_chrdev( 100, testName );
printk( "UnInit testn" );
}
module_init ( test_init_module );
module_exit ( test_cleanup_module );
Using Interrupts
void foo_interrupt(unsigned int irq, struct pt_reg *reg);
irq is the number of the irq which triggered this routine
regs is a copy of the CPU registers
Create Environment
-
8/9/2019 Linux Device Driver Sum Up
39/53
Compiler: gcc -D__KERNEL__ -DMODULE -I/usr/src/linux-2.4.22/include
-c -O -Wall drv.c -o drv.o
Make node: mknod /dev/test c 100 0
Check node:crw-rw-rw- 1 root dialout 4, 64 Jun 30 11:19 test
crw-rw-rw- 1 root dialout 4, 65 Aug 16 00:00 ttyS1
Writing Application
int main(int argc, char *argv[])
{
int fd;
char buf[256] = "Hello World!!";
fd = open( "/dev/test, O_RDWR );
if ( fd == -1 ){
printf( "Open drv driver fail.[Application]n );
return -1;
}
write( fd, buf, 6 );
close( fd );
return 0;
}
14.Accessing Hardware Memory
A Linux user process can not access physical memory directly.
The memory management sc heme which is a demand paged virtual
memory system means that each process has its own address space
(user virtual address space ) that begins at virtual location
zero.
The kernel has its own distinct address space known as the systemvirtual address space .
De chuyen du lieu tu user space vao kernel space: The device driver
copies data between the kernel'y s address space and the user
program'ys address space whenever the user makes a read()or write()
system call
-
8/9/2019 Linux Device Driver Sum Up
40/53
Several Linux routines such as, memcpy_*fs() and put_fs*()
enable device drivers to transfer data across the usersystem
boundary.Data may be transferred in bytes, words, or in buffers
of arbitrary sizes
For example, memcpy_fromfs() transfers an arbitrary number of
bytes of data from user space to the device, while get_fs_byte()
transfers a byte of data from user space.
Similarly, memcpy_tofs() and put_fs_byte() write data to user
space memory
De chuyen du lieu tu kernel space den driver: The transfer of data
between the memory accessible to the kernel and the device itself
is machine dependent.
Some machines require that the CPU execute specia l I/Oinstructions to move data between a device register and
addressable memory often called direct memory access (DMA).
Another scheme, known as memory mapped I/O , implements the
device interface as one or more locations in the memory address
space.
The most common method uses I/O instructions, provided by
the system to allow drivers access the data in a general way
Linux provides inb() to read a single byte from an I/O address
(port) and outb() to write a single byte to an I/O address.The calling syntax is shown here:
unsigned char inb(int port)
outb(char data, int port)
15.Writing a Character Device Drive
Operation Modes
Polling
Interrupt
DMA xxx_write(): The xxx_writ e() routine transfers a character string
of count bytes from the user space memory to the device.
Using interrupts, the hardware is able to interrupt when it is
ready to transfer data and so there is no waiting.
chung ta se co 2 cach viet cho driver: Interrupts vs. Polling
-
8/9/2019 Linux Device Driver Sum Up
41/53
In a polling driver:
Ham nay se duoc viet trong xxx.c
Interrupt-driven drivers are a little more difficult. Here is an example of a
xxx_write() that is interrupt-driven:
-
8/9/2019 Linux Device Driver Sum Up
42/53
-
8/9/2019 Linux Device Driver Sum Up
43/53
memcpy_fromfs() transfers an arbitrary number of bytes of
data from user space to the device,
xxx_table[] is an array of structures, eac h of which have
several members. Some of the members include
xxx_wait_queue and bytes_xfered , which are used for both
reading and writing. The interrupt handling code can use
either request_irq() or irqaction() in the xxx_open()
routine to call xxx_irq[] is an array of 16 integers, and is used for looking up which
entry in xxx_table[] is associated with the irq generated and
reported to the xxx_interrupt() function.
To tell the interrupt-handling code to callxxx_interrupt() , you need
to use either request_irq() or irqaction().This is either done
when xxx_open() is called, or if you want to keep things simple, when
xxx_init()is called. request_irq() is the simpler of the two, and
works rather like an old-style signal handler. It takes two arguments:
the first is the number of the irq you are requesting, and the second isa pointer to your interrupt handler, which must take an integer
argument (the irq that was generated) and have a return type ofvoid.
request_irq() returns -EINVAL ifirq > 15 or if the pointer to the
interrupt handler is NULL, -EBUSY if that interrupt has already been
taken, or 0 on success.
-
8/9/2019 Linux Device Driver Sum Up
44/53
16.Device Driver Initialization
In order that the device driver is correctly initialized when the
operating system is booted, the xxx_init() routine must be executed.
To ensure this happens, add the following line to the end of the
chr_drv_init() function in the /usr/src/linux/driver/char/mem.c
file:
mem_start = xxx_init(mem_start);
and resave the file back to disk.
17.Installing the Driver in the Kernel
Besides functions defined by the file_operations structure, there is at least
one other function that you will have to write, the xxx_init() function.
In order that the device driver is correctly initialized when the
operating system is booted, the xxx_init() routine must be executed.
To ensure this happens, add the following line to the end of the
chr_drv_init() function in the /usr/src/linux/driver/char/mem.c
file:
mem_start = xxx_init(mem_start);
and resave the file back to disk.
xxx_init() should first callregister_chrdev() to register itself and avoiddevice number contention.
-
8/9/2019 Linux Device Driver Sum Up
45/53
int major: This is the major number which the driver wishes to a llocate
char *name: This is the symbolic name of the driver. This is used, among
other things, to report the driver's name in the /proc filesystem.
struct file_operations * xxx_ops (xxx: la ten cua driver): This
is the address of your file_operations structure.
Returns:
0 if no other character device has registered with the same major
number.
non-0 if the call fails, presumably because another character devicehas already allocated that major number.
File Operation on Block Devices
-
8/9/2019 Linux Device Driver Sum Up
46/53
18.Writing LinuxDevice Driver Header files
#include #include
#include
#include
#include
#include
#include
19.Device File Creation
In order to access the device using system calls, a special file
is created. The driver files are normally stored in the /dev
directory of the system. The following commands create the special
device file:
mknod /dev/xxx c 22 0
-
8/9/2019 Linux Device Driver Sum Up
47/53
Creates a special character file named xxx and gives it major number
22 and minor number 0.
chmod 0666 /dev/xxx
Ensures that every user in the system has read/write access to the
device.
20.System call and Library Function call
If you are a C programmer on GNU/Linux and have not used system
calls,then you must have used the library functions
A set of functions available in the standard library that is shipped
with the C compiler for Linux and nonLinux system.
On Linux systems,these library functions are built on top of the
system calls.
system call is built into the kernel. The standard C library offers separate functions to read a block
of data(fread),and a line(fgets),and a single character(fgetc). All
these functions ultimately invoke the only system call available
for reading input read
using system call is usually the most efficient way to perform I/O
operations and is some timemore convenient ,too.
A call to a library function is just like any other function call.
The arguments are placed in the processor register or on to the
stack ,and execution is transfered to the start of the function'scode.
when a program makes system calls ,the arguments are packaged up
and handed to the kernel ,which takes over execution of the program
untill the call completes.
C language:
The first I/O function you likely encountered when you first
learned the C language was printf.This formats a text string and
then prints it to standard output.
The generalized version, fprintf, can print the text to a streamother than standard output.
A stream is represented by a FILE* pointer.
You obtain a FILE* pointer by opening a file with fopen.
When youre done, you can close it with fclose. In addition to fprintf, you can use such functions as fputc,
-
8/9/2019 Linux Device Driver Sum Up
48/53
fputs, and fwrite to write data to the stream, or fscanf, fgetc,
fgets, and fread to read data.
With the Linux low-level I/O operations, you use a handle called
a file descriptor instead of a FILE* pointer. Include the header files , if you use any
of the lowlevel I/O functions described here.
Open
Close
Read
Write
Opening a File Using Open Call
You don't need to open a file to access its attributes.
But,you can't read or write a file unless you first open it. To create a new file descriptor,we need to use the open system
call.
It takes as arguments the path name of the file to open, as
a character string, and flags specifying how to open it(read
or write).
You can use open to create a new file; if you do, pass a third
argument that specifies the access permissions to set for
the new file.
Open returns the file descriptor (nonnegative integer) ifsuccessful,or 1if it fails.
If the second argument is O_RDONLY(or 0), the file is opened
for reading only.
O_WRONLY(or 1) ,the file is opened for writing only.
O_RDWR produces a file descriptor that can be used both for
reading and for writing.
You can specify additional options by using the bitwise or
of this value with one or more flags.
These are the most commonly used values: Specify O_CREAT to create a new file. If the filename that
you provide to open does not exist.
Specify O_EXCL with O_CREAT to force creation of a new
file. If the file already exists, the open call will fail.
Closing a File Using Close call
-
8/9/2019 Linux Device Driver Sum Up
49/53
-
8/9/2019 Linux Device Driver Sum Up
50/53
HEADER
Contains pointers that allow it to chain to other drivers loaded
in the system
First doubleword ( -1) informs that this is last driver in chain. It is followed by attribute word, which indicates type of header
included for driver and type of device the driver installs
The structure of the header attribute word
-
8/9/2019 Linux Device Driver Sum Up
51/53
Strategy Procedure
It is called whenever device driver is loaded in to memory or
whenever I/O requests are issued
Its main purpose is to save the Request header and its address Return Status Word Communicates information back to DOS from
Device Driver.
INTERRUPT PROCEDRE
It uses request header to determine the function requested by
DOS.
It performs all functions for Device Driver
Interrupt Procedure is different from Interrupt Handler.
22.Definition ofDevice
23.Useful Functions #include
int printk(char *fmt, ...);
24.VFS Functions
inode and filp are big kernel structures with data regarding the file and the
device . See
inode: A data structure holding information about files in a Unix file
system. There is an inode for each file and a file is uniquely identified bythe file system on which it resides and its inode number on that system.
Each inode contains the following information:
the device where the inode resides,
locking information,
mode and type of file,
the number oflinks to the file,
the owner's user and
group ids,
the number of bytes in the file, access and modification times,
the time the inode itself was last modified and
The addresses of the file's blocks on disk.
some inportant members
inode->i_rdev: device number of this device, use
-
8/9/2019 Linux Device Driver Sum Up
52/53
MINOR(inode->i_rdev) and MAJOR(inode->i_rdev);
all share the same MAJOR number, but are distinguished by their
MINOR numbers
unsigned int minor = MINOR(inode->i_rdev); /* minor number of device */
ERRNO is one of the error numbers from . Some useful
ERRNOs are
ENODEV - no such device
EBUSY - device busy
EINVAL - invalid operation
fill in the file_operations struct
use NULL for not-implemented members. For example:
25.Giai thich cac cau lenh trong lap trinh driver
interruptible_sleep_on(&xxx_wait_queue); set timeout in case interrupt is
missed. xxx_wait_queue is a FIFO queue of processes that are sleeping; once
initialized (to NULL) the kernel handles the queue and to access it, then supply
a pointer
-
8/9/2019 Linux Device Driver Sum Up
53/53
26.
27.