Wednesday, January 12, 2011

How kernel invokes system call function on linux ?

Guys,

I have mentioned the steps here so that you'll get an idea about the invoking of the system call.

============
1. Executing any command or task. Process has been generated.
2. Process calls library function in user space.
3. Library is consisted of different types of object files and object files contain "system call" function(s). Library also pushes arguments on the stack.
4. Library will issue syscall (int 0x80 / sysenter / ...)
5. Execution will switch to syscall context in kernel mode.
6. kernel will look up systemcall table and dispatch to respective function syscall function in the kernel will handle the syscall. Then result will be returned to the user space.
7. If task is related to any device, kernel will call the device driver (module or subroutine ) and in the mean time it'll send one interrupt to that device so that its driver can access it and process the desired operation and return the result to the kernel. The result will be ok or error and this will be returned to userspace.

Note : Here is the URL for system call table

----
http://bluemaster.iu.hio.no/edu/dark/lin-asm/syscalls.html
----

============

That's it.

Example : I have executed some commands at the user level to give an idea.

command : ls

===========
[root@kmaiti /]# ls //executed command
bin cgroup etc lib lost+found misc mounted NotBackedUp proc root selinux srv tmp var
boot dev home lib64 media mnt net opt remotehome sbin share sys usr VirtualMachines
[root@kmaiti /]# which ls
alias ls='ls --color=auto'
/bin/ls
[root@kmaiti /]# ldd /bin/ls //Depended libraries of the ls binary file
linux-vdso.so.1 => (0x00007fff06dff000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x0000003d45a00000)
librt.so.1 => /lib64/librt.so.1 (0x0000003d44e00000)
libcap.so.2 => /lib64/libcap.so.2 (0x0000003d4de00000)
libacl.so.1 => /lib64/libacl.so.1 (0x0000003929a00000)
libc.so.6 => /lib64/libc.so.6 (0x0000003d43e00000)
libdl.so.2 => /lib64/libdl.so.2 (0x0000003d44600000)
/lib64/ld-linux-x86-64.so.2 (0x0000003d43a00000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003d44200000)
libattr.so.1 => /lib64/libattr.so.1 (0x0000003d54600000)

[root@kmaiti /]# strace ls //Tracing the system call functions
execve("/bin/ls", ["ls"], [/* 27 vars */]) = 0
brk(0) = 0x2618000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7c8998d000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=108955, ...}) = 0
mmap(NULL, 108955, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f7c89972000
close(3) = 0
open("/lib64/libselinux.so.1", O_RDONLY) = 3 //SEE HERE ONE LIBRARY HAS BEEN CALLED
. . . .. . . . .. . . . .. . . . . .. . ..

Here execve, mmap, open, access, fstat, close all are system call functions.

Example of 4th step using assembly language (I am showing how kernel has been called ):

Program : printing "Hello, world!"

--------
[root@kmaiti assembly_test]# cat hello.asm
section .data ;section declaration

msg db "Hello, world!",0xa ;our dear string
len equ $ - msg ;length of our dear string

section .text ;section declaration

;we must export the entry point to the ELF linker or
global _start ;loader. They conventionally recognize _start as their
;entry point. Use ld -e foo to override the default.

_start:

;write our string to stdout

mov edx,len ;third argument: message length
mov ecx,msg ;second argument: pointer to message to write
mov ebx,1 ;first argument: file handle (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel

;and exit

mov ebx,0 ;first syscall argument: exit code
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel

[root@kmaiti assembly_test]# ./hello
Hello, world!
[root@kmaiti assembly_test]#

--------

See kernel has been called at the last line.

===========


Check it out and let me know if you want to suggest anything here :) I appreciate you in advance.

Take care :)

No comments:

Post a Comment