How a linux command uses C system call defined in header files?

In this post, we will check how a linux command executes on the system.

We will learn how a linux command is manipulated by the bash and how it uses the system calls defined in C header files.

For this lets take example of uname command.

1. Uname command description

uname prints information about our software and hardware. A 64-bit machine could be running a 32-bit Linux distribution also.

[root@ngelinux ~]# uname -a
Linux ngelinux 2.6.32-696.el6.i686 #1 SMP Tue Mar 21 18:53:30 UTC 2017 i686 i686 i386 GNU/Linux
[root@ngelinux ~]# 

uname -a prints this information (in order): kernel-name, nodename, kernel-release, kernel-version, machine, processor, hardware-platform, operating-system. If you see 64 bit hardware and i686 kernel, then you have installed a 32-bits Linux kernel.

2. Trace uname command

uname is a system call and we can use starce command to trace the command execution.

The tracing is helpful to understand what all files read by command, however we can’t track what all system calls defined in programming uname.

For this you need to read about linux programming.

[root@ngelinux ~]# strace -v /bin/uname -a
execve("/bin/uname", ["/bin/uname", "-a"], ["HOSTNAME=ngelinux", "SELINUX_ROLE_REQUESTED=", "TERM=xterm", "SHELL=/bin/bash", "HISTSIZE=1000", "SSH_CLIENT=192.168.52.1 64654 22", "SELINUX_USE_CURRENT_RANGE=", "SSH_TTY=/dev/pts/1", "USER=root", "LS_COLORS=rs=0:di=01;34:ln=01;36"..., "LIBGL_DRIVERS_PATH=/usr/lib/dri", "MAIL=/var/spool/mail/root", "PATH=/usr/local/sbin:/usr/local/"..., "PWD=/root", "LANG=en_US.UTF-8", "SELINUX_LEVEL_REQUESTED=", "SSH_ASKPASS=/usr/libexec/openssh"..., "HISTCONTROL=ignoredups", "SHLVL=1", "HOME=/root", "LOGNAME=root", "CVS_RSH=ssh", "SSH_CONNECTION=192.168.52.1 6465"..., "LESSOPEN=||/usr/bin/lesspipe.sh "..., "G_BROKEN_FILENAMES=1", "_=/usr/bin/strace"]) = 0
brk(0)                                  = 0x892e000
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77e7000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_dev=makedev(8, 1), st_ino=663400, st_mode=S_IFREG|0644, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=136, st_size=66865, st_atime=2018/01/14-23:12:07, st_mtime=2018/01/13-23:12:04, st_ctime=2018/01/13-23:12:04}) = 0
mmap2(NULL, 66865, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb77d6000
close(3)                                = 0
open("/lib/libc.so.6", O_RDONLY)        = 3
read(3, "\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\200N\215\0004\0\0\0"..., 512) = 512
fstat64(3, {st_dev=makedev(8, 1), st_ino=920280, st_mode=S_IFREG|0755, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=3744, st_size=1912920, st_atime=2018/01/14-20:48:25, st_mtime=2017/03/21-10:49:29, st_ctime=2017/12/18-05:09:28}) = 0
mmap2(0x8be000, 1665484, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x8be000
mmap2(0xa4f000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x191000) = 0xa4f000
mmap2(0xa52000, 10700, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xa52000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77d5000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb77d56c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
access("/etc/sysconfig/32bit_ssse3_memcpy_via_32bit_ssse3_memmove", F_OK) = -1 ENOENT (No such file or directory)
mprotect(0xa4f000, 8192, PROT_READ)     = 0
mprotect(0x8b6000, 4096, PROT_READ)     = 0
munmap(0xb77d6000, 66865)               = 0
brk(0)                                  = 0x892e000
brk(0x894f000)                          = 0x894f000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_dev=makedev(8, 1), st_ino=142541, st_mode=S_IFREG|0644, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=193704, st_size=99174416, st_atime=2018/01/14-20:50:01, st_mtime=2017/11/14-08:10:11, st_ctime=2017/12/18-05:04:57}) = 0
mmap2(NULL, 2097152, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb75d5000
close(3)                                = 0
uname({sysname="Linux", nodename="ngelinux", release="2.6.32-696.el6.i686", version="#1 SMP Tue Mar 21 18:53:30 UTC 2017", machine="i686", domainname="(none)"}) = 0
fstat64(1, {st_dev=makedev(0, 11), st_ino=4, st_mode=S_IFCHR|0620, st_nlink=1, st_uid=0, st_gid=5, st_blksize=1024, st_blocks=0, st_rdev=makedev(136, 1), st_atime=2018/02/17-03:33:50, st_mtime=2018/02/17-03:33:50, st_ctime=2018/02/16-22:03:15}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77e6000
uname({sysname="Linux", nodename="ngelinux", release="2.6.32-696.el6.i686", version="#1 SMP Tue Mar 21 18:53:30 UTC 2017", machine="i686", domainname="(none)"}) = 0
uname({sysname="Linux", nodename="ngelinux", release="2.6.32-696.el6.i686", version="#1 SMP Tue Mar 21 18:53:30 UTC 2017", machine="i686", domainname="(none)"}) = 0
write(1, "Linux ngelinux 2.6.32-696.el6.i6"..., 96Linux ngelinux 2.6.32-696.el6.i686 #1 SMP Tue Mar 21 18:53:30 UTC 2017 i686 i686 i386 GNU/Linux
) = 96
close(1)                                = 0
munmap(0xb77e6000, 4096)                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++
[root@ngelinux ~]# 

3. uname system call

We have got below program from web page: https://askubuntu.com/questions/724415/where-is-uname-pulling-information-from and its copyright to specific author and not NGEL.

#include < stdio.h > // Contains printf() command.
#include < sys/utsname.h >  // It is the library containing the uname system call.

int main() {
        int ret; // stores the return value of uname()
        struct utsname utsname; // stores the data returned by uname()
        struct utsname *utsname_ptr = &utsname; // pointer to the struct holding the data returned by uname()

        ret = uname(utsname_ptr); // calls uname() on utsname_ptr and stores its return value in ret

        /* prints the fields of utsname */

        printf("%s\n", utsname.sysname);
        printf("%s\n", utsname.nodename);
        printf("%s\n", utsname.release);
        printf("%s\n", utsname.version);
        printf("%s\n", utsname.machine);

        /* returns the return value of uname() */

        return(ret);
}

From the above program, it is clear that uname command uses the system calls as defined in utsname.h header file.

Similar to uname command, every command uses C libraries/header files, and the calls defined in them.

Leave a Reply

avatar
  Subscribe  
Notify of