When there is a definitive guide to learn Linux system programming, it is heaven to read and practice those examples. Some times we may need to implement some function which is available in the well known tools (or commercial tools), but we may not know which system call to use to accomplish some of the tasks. I too faced such problems. Then I found that strace is handy command for this purpose. This is very much useful for debugging purpose.
For example if I want to trace what system calls are used by fdisk while I am listing all partitions in my system (fdisk -l), here is the command with strace feature:
Here is the fdisk-trace.log file which lists all system calls called by fdisk with argument and return values.:
execve(“/sbin/fdisk”, ["/sbin/fdisk", "-l"], [/* 26 vars */]) = 0
uname({sys=”Linux”, node=”pr000.hcl.cp.net”, …}) = 0
brk(0) = 0×805ff48
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0×40016000
open(“/etc/ld.so.preload”, O_RDONLY) = -1 ENOENT (No such file or directory)
open(“/etc/ld.so.cache”, O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=75477, …}) = 0
old_mmap(NULL, 75477, PROT_READ, MAP_PRIVATE, 3, 0) = 0×40017000
close(3) = 0
open(“/lib/tls/libc.so.6″, O_RDONLY) = 3
read(3, “\177ELF\1\1\1\3\3\1`V\1B4″…, 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1531064, …}) = 0
old_mmap(0×42000000, 1257224, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0×42000000
old_mmap(0×4212e000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0×12e000) = 0×4212e000
old_mmap(0×42131000, 7944, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0×42131000
close(3) = 0
set_thread_area({entry_number:-1 -> 6, base_addr:0×40016a20, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
munmap(0×40017000, 75477) = 0
brk(0) = 0×805ff48
brk(0×8060f48) = 0×8060f48
brk(0) = 0×8060f48
brk(0×8061000) = 0×8061000
open(“/usr/lib/locale/locale-archive”, O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=30301680, …}) = 0
mmap2(NULL, 2097152, PROT_READ, MAP_PRIVATE, 3, 0) = 0×40017000
close(3) = 0
open(“/proc/partitions”, O_RDONLY|O_LARGEFILE) = 3
It accesses /proc/partitions pseudo file for partition information.
read(3, “major minor #blocks name r”…, 32768) = 412
open(“/proc/ide/hda/media”, O_RDONLY|O_LARGEFILE) = 4
It accesses /proc/ide/hda/media for type of storage device. This /proc/ide/hda has more harddisk related description and settings details.
fstat64(4, {st_mode=S_IFREG|0444, st_size=0, …}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0×40217000
read(4, “disk\n”, 4096) = 5
close(4) = 0
munmap(0×40217000, 4096) = 0
open(“/dev/hda”, O_RDONLY|O_LARGEFILE) = 4
open(“/dev/hda”, O_RDONLY|O_LARGEFILE) = 5
It opens /dev/hda and gets the handle.
read(5, “\353H\220lbaLILO\1\25\4Z\vW4=\3640\300\1″…, 512) = 512
uname({sys=”Linux”, node=”pr000.hcl.cp.net”, …}) = 0
ioctl(5, BLKSSZGET, 0xbfff73e4) = 0
fstat64(5, {st_mode=S_IFBLK|0660, st_rdev=makedev(3, 0), …}) = 0
ioctl(5, 0×301, 0xbfff73e0) = 0
ioctl(5, BLKGETSIZE, 0xbfff7408) = 0
Handle of /dev/hda used to call ioctl implemented by /dev/hda driver. The IOCTL code BLKSSZGET gets the size of a block
_llseek(5, 0, [0], SEEK_SET) = 0
read(5, “\353H\220lbaLILO\1\25\4Z\vW4=\3640\300\1″…, 8192) = 8192
close(5) = 0
open(“/usr/share/locale/locale.alias”, O_RDONLY) = 5
fstat64(5, {st_mode=S_IFREG|0644, st_size=2601, …}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0×40217000
read(5, “# Locale name alias data base.\n#”…, 4096) = 2601
brk(0) = 0×8061000
brk(0×8062000) = 0×8062000
read(5, “”, 4096) = 0
close(5) = 0
munmap(0×40217000, 4096) = 0
open(“/usr/share/locale/en_US.UTF-8/LC_MESSAGES/util-linux.mo”, O_RDONLY) = -1 ENOENT (No such file or directory)
open(“/usr/share/locale/en_US.utf8/LC_MESSAGES/util-linux.mo”, O_RDONLY) = -1 ENOENT (No such file or directory)
open(“/usr/share/locale/en_US/LC_MESSAGES/util-linux.mo”, O_RDONLY) = -1 ENOENT (No such file or directory)
open(“/usr/share/locale/en.UTF-8/LC_MESSAGES/util-linux.mo”, O_RDONLY) = -1 ENOENT (No such file or directory)
open(“/usr/share/locale/en.utf8/LC_MESSAGES/util-linux.mo”, O_RDONLY) = -1 ENOENT (No such file or directory)
open(“/usr/share/locale/en/LC_MESSAGES/util-linux.mo”, O_RDONLY) = -1 ENOENT (No such file or directory)
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), …}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0×40217000
write(1, “\n”, 1) = 1
write(1, “Disk /dev/hda: 20.5 GB, 20547841″…, 42) = 42
write(1, “255 heads, 63 sectors/track, 249″…, 44) = 44
write(1, “Units = cylinders of 16065 * 512″…, 50) = 50
write(1, ” Device Boot Start En”…, 57) = 57
open(“/usr/lib/gconv/gconv-modules.cache”, O_RDONLY) = 5
fstat64(5, {st_mode=S_IFREG|0644, st_size=21040, …}) = 0
mmap2(NULL, 21040, PROT_READ, MAP_SHARED, 5, 0) = 0×40218000
close(5) = 0
write(1, “/dev/hda1 * 1 1″…, 56) = 56
write(1, “/dev/hda2 14 236″…, 56) = 56
write(1, “/dev/hda3 2369 249″…, 61) = 61
read(3, “”, 32768) = 0
close(3) = 0
munmap(0×40217000, 4096) = 0
exit_group(0) = ?
I hope this information will sure be helpful to those who don’t know such a nice feature exists in Linux command line.