kernel筆記——庫文件與系統調用
庫文件
先從我們熟悉的c庫入手,理解系統調用(system call)。c代碼中調用printf函數,經歷了以下調用過程:
最終輸出的功能由內核中write調用完成,c庫封裝了系統調用。
對於以下hello world程序:
#include int main() { printf("Hello world.\n"); return 0; }
我們可以使用ldd查看程序依賴的庫文件:
linux # ldd hello linux-vdso.so.1 => (0x00007fff89fe2000) libc.so.6 => /lib64/libc.so.6 (0x00007fd142094000) /lib64/ld-linux-x86-64.so.2 (0x00007fd1423f2000)
輸出結果中顯示了hello程序依賴的動態庫文件,其中linux-vdso.so.1指向進程虛擬內存地址,是一個虛擬的庫文件,在每個程序的虛擬內存都存在,其將內核態的調用映射到用戶地址空間中,使得調用開銷更小。
有些時候,在我們編譯程序時,會出現找不到某某lib的提示,又或者ldd查詢到某庫鏈接指示”not found”,這是因為ldd在/etc/ld.so.cache中不存在相應庫文件的查找路徑(使用strace跟蹤ldd命令可以看到ld.so.cache文件被讀取)。
要解決找不到某庫的問題,我們可以將庫文件路徑加到用戶的LIBRARY_PATH環境變量中,也可以添加到全局的/etc/ld.so.conf配置文件中,添加完後以root用戶執行ldconfig,以更新/etc/ld.so.cache緩存文件。
使用rpm命令可以查到動態庫屬於哪個rpm包:
linux # rpm -qf /lib64/libc.so.6 glibc-2.11.1-0.17.4
反過來,對某一rpm包,我們可以查其包含的內容:
linux # rpm -ql glibc-2.11.1-0.17.4 /etc/bindresvport.blacklist /etc/default/nss /etc/gai.conf /etc/ld.so.cache /etc/ld.so.conf ……
devel包中包含了c庫函數的頭文件,而普通包中不包含頭文件,可以使用rpm查詢對比開發包和普通包:
rpm -ql glibc-2.4-31.77.88.4 rpm -ql glibc-devel-2.4-31.77.88.4
系統調用
每一個系統調用對應一個系統調用號(system call number),使用系統調用的過程就是將系統調用號和參數傳遞給內核。
使用objdump,可以對庫文件進行反匯編,以下對/lib64/libc.so.6進行反匯編,並查看getpid函數相應的部分匯編代碼:
00000000000933e0 <__getpid>: …… 933fa: 00 933fb: 85 c0 test %eax,%eax 933fd: 75 f0 jne 933ef <__getpid+0xf> 933ff: b8 27 00 00 00 mov $0x27,%eax 93404: 0f 05 syscall 93406: 85 d2 test %edx,%edx ……
在以上輸出中,mov指令將系統調用號0x27放入eax寄存器中,0x27作為syscall的參數,syscall完成調用getpid的工作。
系統調用與系統調用號對應關系在include/asm/unistd.h中定義,我們可以查到getpid相應的定義語句:
#define __NR_getpid 39 __SYSCALL(__NR_getpid, sys_getpid)
unistd.h定義了POSIX標準提供的系統調用,所有符合POSIX標準的Unix系統均提供該頭文件。
我們可以直接傳遞系統調用號給syscall函數,完成系統調用,以下程序說明了如何使用syscall直接完成getpid系統調用:
#define _GNU_SOURCE #include #include #include #include int main(int argc, char *argv[]) { pid_t tid; tid = syscall(SYS_gettid); printf("%d\n", tid); }
因而總結來說,使用系統調用的方式有兩種:
- c庫中封裝了系統調用,通過c庫間接調用
- 傳遞系統調用號,通過syscall直接調用
第2種方式存在的意義在於,當kernel提供了新的系統調用,而c庫又沒有更新時,可以使用syscall調用新的系統調用。
Reference: Chapter 5 - System Calls, Linux kernel development.3rd.Edition
kernel筆記——庫文件與系統調用