System Call 專題討論, #2:使用 C 語言呼叫 System Call

jollen 發表於 December 1, 2006 4:24 PM

在 Linux system 底下,必須透過 GLIBC 裡的 system call function 來取得 kernel 的 system call 服務。

由 GLIBC 提供用來呼叫 system call 的函數稱為 wrapper function,wrapper function會呼叫 Linux kernel的handler routine,即 system_call() 函數。

呼叫 getpid() system call 的範例:

#include 
#include 
#include 

int main()
{
   pid_t self, parent;

   self = getpid();
   parent = getppid();

   printf("PID: %d, Parent PID: %d\n", (int) self, (int) parent);
   return 0;
}

利用 strace 工具可以追蹤程式所使用到的 system call:

$ strace ./pid
execve("./pid", ["./pid"], [/* 25 vars */]) = 0
uname({sys="Linux", node="jollen", ...}) = 0
brk(0)                                  = 0x80495ac
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=114793, ...}) = 0
old_mmap(NULL, 114793, 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\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0`V\1B4\0"..., 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:0x400169e0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
munmap(0x40017000, 114793)              = 0
getpid()                                = 970
getppid()                               = 969
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40017000
write(1, "PID: 970, Parent PID: 969\n", 26) = 26
munmap(0x40017000, 4096)                = 0
exit_group(0)                           = ?

由 strace 的輸出結果可以得知程式所呼叫的 system call,在這裡我們可以看到 getpid()getppid(),並且也能得知 printf() 是基於 write() system call。

讀者留言 (0)

留言功能維護中。將於近日重新開放。

連絡作者

Jollen Chen,Moko365(仕橙3G教室)講師,熱愛研究 Linux 與 Android 技術。曾為 Motorola、HTC、Foxconn、LG、OPPO、騰迅、廣達電腦、緯創、仁寶等超過 50 家企業講授課程。目前在 MokoVersity 擔任軟體工程師,撰寫 Node.js 程式,也在幾家科技廠兼任 Android Framework 研發顧問。您可透過電子郵件 <jollen (at) jollen (dot) org> 或這裡與我連絡。