Implementing Linux System Calls
This article is based on my experiences in creating and installing a system call in Linux and how to install one interrupt vector to control the serial port. In one way, this is a mini-HOWTO about these two topics.
A system call (or system request) is a call to the kernel in order to execute a specific function that controls a device or executes a privileged instruction. The way system calls are handled is up to the processor. Usually, a call to the kernel is due to an interrupt or exception; in the call, there is a request to execute something special. For example, the serial port may be programmed to assert an interrupt when some character has arrived, instead of polling for it. This way, the processor can be used by other processes and service the serial port only when it is required.
The internal operation between an interrupt request and its servicing involve several CPU registers and memory segments. Briefly, a device raises an interrupt by asserting an interrupt request line on the Peripheral Interrupt Controller (PIC) which informs the CPU by setting the interrupt request pin. After each instruction, the CPU checks this pin. If it is enabled, it gets the ID from the data bus, which points to the Interrupt Descriptor Table (IDT), where a number of task, interrupt and gate descriptors are stored. The descriptor contains a selector to the Global Descriptor Table (GDT) which contains the base address to a memory segment in which the Interrupt Service Routine (ISR) resides.
Note that the CPU has suspended the process it was executing, so it has to save some information to be able to resume the process after the interrupt has been serviced—this is a context switching. Several files are involved in this process; most can be found in the linux/arch/i386/kernel/ directory. One is entry.S, an entry point to all system calls which initializes the treatment of exceptions. Another is irq.c, which contains the functions to deal with interrupts. The linux/arch/i386/boot/setup.S file initializes the GDT, installs virtual memory, etc. There are many connections between files ending in .h and .c. You can check irq.c to see how many includes are there to get macros definitions, such as cli(), which clears interrupts in linux/include/asm-i386/system.h.
To follow the definition path of any function, type at your command prompt:
grep cli 'find / -name '*.[ch]' -print'
This will search all files with extension c and h in the root directory for the word cli. Also, you can issue the command man 2 intro to see something about system calls.
There are several ways to create, install and execute a system call. The best is the one that isn't concerned with low-level details like context switching and doesn't code any routines in assembly language. This can be done through the use of the _syscallN macro in the linux/include/asm/unistd.h directory; it is expanded in assembly, but the operating system takes care of details. It uses the int 0x80 to transfer execution control to the kernel. One possible problem is this macro can expand to an existing function, so care must be taken; otherwise, you will overwrite the existing function.
In order to implement your own system calls, you should have the Linux kernel source code (first make a backup) to use as the working copy. As superuser (root), create in your home directory an entire tree copy of /usr/src/linux, as you will not have the chance to do so again. The files we will use are in somewhere/linux/.
Now you must choose a name for every function you are planning to implement. You can check the existing ones in your source tree at linux/arch/i386/kernel/entry.S and linux/include/asm/unistd.h. In entry.S, they are at the end, and in unistd.h, at the beginning. Checking these files will also help you get an idea of how to create a prototype of a system call. While checking, you will see that each call is associated with one number. This number is passed in the %eax processor register indicating the number of arguments, and each argument of the system call (a function) is passed in %ebx, %ecx, %edx, %esi or %edi--up to five arguments on Intel platforms. The macro definitions corresponding to each _syscallN, depending on the value of N, can be found in unistd.h. More on the internal workings can be found in various files under linux/arch/i386/, because we will leave the “dirty work” to the operating system.
Now let's see how to implement a new system call using the syscallN macro in the simplest possible way. Let's make a system call sysSum, which accepts two integer arguments and returns the sum of the two. Also, it uses printk, which is similar to printf except that it works on the kernel level, so we will see when our function is called.
To do this, edit a randomly selected file (for example, the file linux/ipc/sem.c), and at the end, add the following lines:
asmlinkage int sysSum(int a, int b)
{
printk("calling sysSum\n");
return a+b;
}
Then edit unistd.h and add
#define __NR_sysSum 171171 is the next in numerical order. In entry.S near the end, add
.long SYMBOL_NAME(sysSum)Finally, increment by one the number that is the last line:
.space (NR_syscall-172)*4If you don't match number and name in both files, you will get an “undefined reference to sysSum” error message. If you have a working kernel, you have to be careful only about incrementing the numbers by one and correctly writing your function name. At this point, you have added your system call; now you should get the new kernel with it. To recompile the kernel, take the following sequential steps:
#make config #make dep #make clean #make zImage #cat ~/linux/arch/i386/boot/zImage >/dev/fd0Step 1 creates the basic kernel configuration; you can skip it next time if no hardware changes are made. Step 2 checks that any dependency between files is correct. Step 3 cleans any compilation intermediate file (object files, etc.). The last two create a compressed kernel image and copy it to floppy, so we can try our new kernel and keep the original one untouched.
Reboot using this newly created kernel to invoke the system call from a user program: simply insert the floppy disk on the drive and reboot. This simple program tests the newly created system call:
#include <linux/unistd.h>
_syscall2(int, sysSum, int,a,int,b)
main(){
printf("the sum of 4+3 is %d\n",sysSum(4,3));
}
The include line indicates where the _syscall definition is located. The next line says our system call has a return type of int and two arguments of type int. To compile, use the command
gcc -I ~/linux/includeto instruct the compiler to use our include file. After execution, you will see messages: first the one from sysSum, then the one from the test program.
The functions we will implement will be the basic ones needed to control the serial port using interrupts on character reception. The serial ports can't be accessed by a common user. In Linux, the functions inb(port) and outb(byte, port) exist to receive and send one byte; inw and outw do the same on two-byte data. In order to use them, you have to gain the rights by using the iopl or ioperm functions, which must be invoked as super user and will give the common user application access to the I/O ports.
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Sponsored by AMD
If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.
Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.
Sponsored by ActiveState
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?
| Non-Linux FOSS: libnotify, OS X Style | Jun 18, 2013 |
| Containers—Not Virtual Machines—Are the Future Cloud | Jun 17, 2013 |
| Lock-Free Multi-Producer Multi-Consumer Queue on Ring Buffer | Jun 12, 2013 |
| Weechat, Irssi's Little Brother | Jun 11, 2013 |
| One Tail Just Isn't Enough | Jun 07, 2013 |
| Introduction to MapReduce with Hadoop on Linux | Jun 05, 2013 |
- Containers—Not Virtual Machines—Are the Future Cloud
- Non-Linux FOSS: libnotify, OS X Style
- Lock-Free Multi-Producer Multi-Consumer Queue on Ring Buffer
- Linux Systems Administrator
- Validate an E-Mail Address with PHP, the Right Way
- Introduction to MapReduce with Hadoop on Linux
- RSS Feeds
- Weechat, Irssi's Little Brother
- New Products
- Tech Tip: Really Simple HTTP Server with Python
- Reply to comment | Linux Journal
13 min 30 sec ago - Didn't read
23 min 50 sec ago - Reply to comment | Linux Journal
28 min 50 sec ago - Poul-Henning Kamp: welcome to
2 hours 38 min ago - This has already been done
2 hours 39 min ago - Reply to comment | Linux Journal
3 hours 25 min ago - Welcome to 1998
4 hours 13 min ago - notifier shortcomings
4 hours 37 min ago - heroku?
6 hours 14 min ago - Android User
6 hours 15 min ago




Comments
syscalls.kernelgrok.com
There is an updated list of Linux system calls here syscalls.kernelgrok.com.
Implent by S/m call
The Concept of Implement System Calls in C program is Realy helping to Development of My Small Project.Lab Section. So I am realy Thanks.............................
excellent
really its good . every step is mentioned in very clear manner.
Great Article
It's a great article that I ever have seen. Thanks a lot for this. It has cleared some confusion regarding the system call and their interface.
re:artical
its the nice artical.those who want to do the work in the area of system programming should read this one.
Nice Article
This is really a nice article. Many important things are eloberated nicely here. All system programmers, linux explorers should read this article. :)