Any application running on Linux may request services like :
- Inter process communication
- I/O services
- Creating a new process
- Accessing system hardware etc
Note: The above list is not exhaustive.
The services listed above are all handled by Linux kernel. So, any application in Linux that requires any of these services has to request the Linux kernel to handle the request on its behalf. The request is handed over to kernel by calling corresponding system calls. System calls act as an interface between application and kernel.
Some examples of system calls include :
How system call works
- write() etc
The following points explain the operation of a system call on x86-32 hardware:
- From a programmer point of view, calling a system call is equivalent to calling any normal C function.
- Inside the Linux kernel, each system call has a number associated with it.
- The kernel expects all the information like system call number, the arguments to the system call etc to be present in CPU registers.
- A system call first invokes a C library wrapper function which does all this work of placing the information required to be placed in CPU registers. The system call number is placed in the register %eax.
- After doing the above work, the same wrapper function invokes a trap instruction 'int 0x80'. This instruction switches the processor mode from user mode to the kernel mode and executes the code kept at location 0x80.
Note : Starting with Linux kernel 2.6 and glibc 2.3.2 a faster mechanism of using the 'sysenter' instruction is followed to switch into the kernel mode.
- After the above step, now since the processor is in kernel mode, the kernel calls a general trap handler function system_call() to handle this trap.
- This handler function : Copies all the relevant information kept in the CPU registers onto the kernel stack, Validates the system call number, Uses the system call number to find the corresponding system call service routine from a table(sys_call_table) of service routines maintained by kernel and Calls the system call service routine with the arguments passed from the user space.
- The system call service routine that is finally called by the trap handler first checks the validity of the arguments sent to it and then it does the actual work requested by the application.
- Once the system call service routine is done with its processing, the control is returned back to the trap handler function which returns the flow back to the wrapper function in the user-mode.
- Based on the return value from the trap handler, the wrapper function sets the 'errno' variable and returns -1 (in most of the cases) to indicate an error.
- The value of the 'errno' variable is assigned by negating the return value of the trap handler (returned to wrapper function).
- The application can use the strerror() API with 'errno' to get the error information in form of human readable string.
An example of using 'errno' and strerror() is given below :
int main(int argc, char *argv)
if(2 != argc)
printf("\n Usage : \n");
errno = 0;
fd = open(argv,O_RDWR);
if(-1 == fd)
printf("\n open() failed with errorno[%d] and error [%s]\n",errno, strerror(errno));
printf("\n Open() Successful\n");
If the above program is run with a file name that does not exist then following is the output :
$ ./open Linux
open() failed with errorno and error [No such file or directory]
So we see that on failure, errno is updated to value '2' and strerror() returns a human readable string "No such file or directory".