Difference between static and dynamic linking

Lets write a simple helloworld program and using which we will try to understand the difference between static and dynamic linking.

 $ vim helloworld.c 
#include <stdio.h>
int main(int argc, char **argv) { printf("Hello World !"); return 0;
}

Now, we will try to compile this program as,

 $ gcc -o helloworld helloworld.c 
 $ file helloworld
helloworld: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=57cffc47f6d9d1f05a43c3b1cda6bc43d4f95dbf, not stripped 
 $ ldd helloworld	linux-gate.so.1 => (0xb773e000)	libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7559000)	/lib/ld-linux.so.2 (0x8008a000)

Above two commands, “file” and “ldd” shows that by default “gcc” created dynamically linked executable.

Now, lets try to create “statically linked” executable of same program as,

 $ gcc -o helloworld_static helloworld.c -static 
 $ file helloworld_static helloworld_static: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=a7cc1db70ccce3a1640579f2637e8d5ee1a6b9e4, not stripped 
 $ ldd helloworld_static	not a dynamic executable 

Above two commands shows we now have a “statically linked” executable.

Now lets try to compare the file sizes of both executable as,

 $ ls -alh helloworld
-rwxrwxr-x 1 myuser myuser 7.2K Sep 2 21:08 helloworld
$ size helloworld text data bss dec hex	filename 1124 276 4 1404 57c	helloworld
$ ls -alh helloworld_static
-rwxrwxr-x 1 myuser myuser 712K Sep 2 21:08 helloworld_static
$ size helloworld_static text data bss dec hex	filename 658287 4096 3644 666027 a29ab	helloworld_static

So above two commands, shows that dynamically linked executable “helloworld” generates much smaller in size (7.2K) binary compared to statically linked executable “helloworld_static” (712K)

So the first difference is that, statically linked executable requires more space compared to dymanically linked executables which is the disadvantage of static linking and advantage of dynamic linking.

Another difference is, If several processes call the same object module of a shared library simultaneously, Only one copy of shared library resides in memory for dynamically linked executables where as for static linking all things of library gets copied as part of static linking hence Several copies each for a process resides in memory.

 $ strace ./helloworld
execve("./helloworld", ["./helloworld"], [/* 69 vars */]) = 0
brk(NULL) = 0x9046000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb76ee000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=170313, ...}) = 0
mmap2(NULL, 170313, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb76c4000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\320\207\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1786484, ...}) = 0
mmap2(NULL, 1792540, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb750e000
mmap2(0xb76be000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1af000) = 0xb76be000
mmap2(0xb76c1000, 10780, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb76c1000
close(3) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7715000
set_thread_area({entry_number:-1, base_addr:0xb7715940, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 (entry_number:6)
mprotect(0xb76be000, 8192, PROT_READ) = 0
mprotect(0x8049000, 4096, PROT_READ) = 0
mprotect(0xb7716000, 4096, PROT_READ) = 0
munmap(0xb76c4000, 170313) = 0
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 13), ...}) = 0
brk(NULL) = 0x9046000
brk(0x9067000) = 0x9067000
write(1, "Hello World !", 13Hello World !) = 13
exit_group(0) = ?
+++ exited with 0 +++
 $ strace ./helloworld_static
execve("./helloworld_static", ["./helloworld_static"], [/* 69 vars */]) = 0
uname({sysname="Linux", nodename="nms-bot-server", ...}) = 0
brk(NULL) = 0x88e5000
brk(0x88e5d40) = 0x88e5d40
set_thread_area({entry_number:-1, base_addr:0x88e5840, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 (entry_number:6)
readlink("/proc/self/exe", "/home/myuser/githu"..., 4096) = 97
brk(0x8906d40) = 0x8906d40
brk(0x8907000) = 0x8907000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 13), ...}) = 0
write(1, "Hello World !", 13Hello World !) = 13
exit_group(0) = ?
+++ exited with 0 +++

The above commands where we tried to run both executables with strace shows, dynamic linking has more system calls, which means dynamic linked executables will need more time for running/execution.

READ  Wi-Fi Initial Communication between device and access point

Leave a Reply

Your email address will not be published. Required fields are marked *