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) = 0x805ff48
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40016000
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) = 0x40017000
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(0x42000000, 1257224, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x42000000
old_mmap(0x4212e000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x12e000) = 0x4212e000
old_mmap(0x42131000, 7944, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x42131000
close(3) = 0
set_thread_area({entry_number:-1 -> 6, base_addr:0x40016a20, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
munmap(0x40017000, 75477) = 0
brk(0) = 0x805ff48
brk(0x8060f48) = 0x8060f48
brk(0) = 0x8060f48
brk(0x8061000) = 0x8061000
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) = 0x40017000
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) = 0x40217000
read(4, “disk\n”, 4096) = 5
close(4) = 0
munmap(0x40217000, 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, 0x301, 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) = 0x40217000
read(5, “# Locale name alias data base.\n#”…, 4096) = 2601
brk(0) = 0x8061000
brk(0x8062000) = 0x8062000
read(5, “”, 4096) = 0
close(5) = 0
munmap(0x40217000, 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) = 0x40217000
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) = 0x40218000
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(0x40217000, 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.