什么是系統(tǒng)調(diào)用?
Linux內(nèi)核中設(shè)置了一組用于實(shí)現(xiàn)各種系統(tǒng)功能的子程序,稱為系統(tǒng)調(diào)用。用戶可以通過系統(tǒng)調(diào)用命令在自己的應(yīng)用程序中調(diào)用它們。從某種角度來看,系統(tǒng)調(diào)用和普通的函數(shù)調(diào)用非常相似。區(qū)別僅僅在于,系統(tǒng)調(diào)用由操作系統(tǒng)核心提供,運(yùn)行于核心態(tài);而普通的函數(shù)調(diào)用由函數(shù)庫或用戶自己提供,運(yùn)行于用戶態(tài)。
隨Linux核心還提供了一些C語言函數(shù)庫,這些庫對系統(tǒng)調(diào)用進(jìn)行了一些包裝和擴(kuò)展,因?yàn)檫@些庫函數(shù)與系統(tǒng)調(diào)用的關(guān)系非常緊密,所以習(xí)慣上把這些函數(shù)也稱為系統(tǒng)調(diào)用。
為什么要用系統(tǒng)調(diào)用?
實(shí)際上,很多已經(jīng)被我們習(xí)以為常的C語言標(biāo)準(zhǔn)函數(shù),在Linux平臺(tái)上的實(shí)現(xiàn)都是靠系統(tǒng)調(diào)用完成的,所以如果想對系統(tǒng)底層的原理作深入的了解,掌握各種系統(tǒng)調(diào)用是初步的要求。進(jìn)一步,若想成為一名Linux下編程高手,也就是我們常說的Hacker,其標(biāo)志之一也是能對各種系統(tǒng)調(diào)用有透徹的了解。
即使除去上面的原因,在平常的編程中你也會(huì)發(fā)現(xiàn),在很多情況下,系統(tǒng)調(diào)用是實(shí)現(xiàn)你的想法的簡潔有效的途徑,所以有可能的話應(yīng)該盡量多掌握一些系統(tǒng)調(diào)用,這會(huì)對你的程序設(shè)計(jì)過程帶來意想不到的幫助。
系統(tǒng)調(diào)用是怎么工作的?
一般的,進(jìn)程是不能訪問內(nèi)核的。它不能訪問內(nèi)核所占內(nèi)存空間也不能調(diào)用內(nèi)核函數(shù)。CPU硬件決定了這些(這就是為什么它被稱作"保護(hù)模式")。系統(tǒng)調(diào)用是這些規(guī)則的一個(gè)例外。其原理是進(jìn)程先用適當(dāng)?shù)闹堤畛?a href="http://m.xsypw.cn/tags/寄存器/" target="_blank">寄存器,然后調(diào)用一個(gè)特殊的指令,這個(gè)指令會(huì)跳到一個(gè)事先定義的內(nèi)核中的一個(gè)位置(當(dāng)然,這個(gè)位置是用戶進(jìn)程可讀但是不可寫的)。在Intel CPU中,這個(gè)由中斷0x80實(shí)現(xiàn)。硬件知道一旦你跳到這個(gè)位置,你就不是在限制模式下運(yùn)行的用戶,而是作為操作系統(tǒng)的內(nèi)核--所以你就可以為所欲為。
進(jìn)程可以跳轉(zhuǎn)到的內(nèi)核位置叫做sysem_call。這個(gè)過程檢查系統(tǒng)調(diào)用號(hào),這個(gè)號(hào)碼告訴內(nèi)核進(jìn)程請求哪種服務(wù)。然后,它查看系統(tǒng)調(diào)用表(sys_call_table)找到所調(diào)用的內(nèi)核函數(shù)入口地址。接著,就調(diào)用函數(shù),等返回后,做一些系統(tǒng)檢查,最后返回到進(jìn)程(或到其他進(jìn)程,如果這個(gè)進(jìn)程時(shí)間用盡)。
具體過程如下圖所示:
如何使用系統(tǒng)調(diào)用?
先來看一個(gè)例子:
這是因?yàn)樵?a href="http://m.xsypw.cn/tags/ti/" target="_blank">time.h中實(shí)際上已經(jīng)用庫函數(shù)的形式實(shí)現(xiàn)了time這個(gè)系統(tǒng)調(diào)用,替我們省掉了調(diào)用_syscall1宏展開得到函數(shù)原型這一步。
大多數(shù)系統(tǒng)調(diào)用都在各種C語言函數(shù)庫中有所實(shí)現(xiàn),所以在一般情況下,我們都可以像調(diào)用普通的庫函數(shù)那樣調(diào)用系統(tǒng)調(diào)用,只在極個(gè)別的情況下,我們才有機(jī)會(huì)用到_syscall*()這幾個(gè)宏。
調(diào)用性能問題
系統(tǒng)調(diào)用需要從用戶空間陷入內(nèi)核空間,處理完后,又需要返回用戶空間。其中除了系統(tǒng)調(diào)用服務(wù)例程的實(shí)際耗時(shí)外,陷入/返回過程和系統(tǒng)調(diào)用處理程序(查系統(tǒng)調(diào)用表、存儲(chǔ)\恢復(fù)用戶現(xiàn)場)也需要花銷一些時(shí)間,這些時(shí)間加起來就是一個(gè)系統(tǒng)調(diào)用的響應(yīng)速度。系統(tǒng)調(diào)用不比別的用戶程序,它對性能要求很苛刻,因?yàn)樗枰萑雰?nèi)核執(zhí)行,所以和其他內(nèi)核程序一樣要求代碼簡潔、執(zhí)行迅速。幸好Linux具有令人難以置信的上下文切換速度,使得其進(jìn)出內(nèi)核都被優(yōu)化得簡潔高效;同時(shí)所有Linux系統(tǒng)調(diào)用處理程序和每個(gè)系統(tǒng)調(diào)用本身也都非常簡潔。
絕大多數(shù)情況下,Linux系統(tǒng)調(diào)用性能是可以接受的,但是對于一些對性能要求非常高的應(yīng)用來說,它們雖然希望利用系統(tǒng)調(diào)用的服務(wù),但卻希望加快相應(yīng)速度,避免陷入/返回和系統(tǒng)調(diào)用處理程序帶來的花銷,因此采用由內(nèi)核直接調(diào)用系統(tǒng)調(diào)用服務(wù)例程,最好的例子就HTTPD——它為了避免上述開銷,從內(nèi)核調(diào)用socket等系統(tǒng)調(diào)用服務(wù)例程。
Linux系統(tǒng)調(diào)用列表
· 進(jìn)程控制
fork 創(chuàng)建一個(gè)新進(jìn)程
clone 按指定條件創(chuàng)建子進(jìn)程
execve 運(yùn)行可執(zhí)行文件
exit 中止進(jìn)程
_exit 立即中止當(dāng)前進(jìn)程
getdtablesize 進(jìn)程所能打開的最大文件數(shù)
getpgid 獲取指定進(jìn)程組標(biāo)識(shí)號(hào)
setpgid 設(shè)置指定進(jìn)程組標(biāo)志號(hào)
getpgrp 獲取當(dāng)前進(jìn)程組標(biāo)識(shí)號(hào)
setpgrp 設(shè)置當(dāng)前進(jìn)程組標(biāo)志號(hào)
getpid 獲取進(jìn)程標(biāo)識(shí)號(hào)
getppid 獲取父進(jìn)程標(biāo)識(shí)號(hào)
getpriority 獲取調(diào)度優(yōu)先級(jí)
setpriority 設(shè)置調(diào)度優(yōu)先級(jí)
modify_ldt 讀寫進(jìn)程的本地描述表
nanosleep 使進(jìn)程睡眠指定的時(shí)間
nice 改變分時(shí)進(jìn)程的優(yōu)先級(jí)
pause 掛起進(jìn)程,等待信號(hào)
personality 設(shè)置進(jìn)程運(yùn)行域
prctl 對進(jìn)程進(jìn)行特定操作
ptrace 進(jìn)程跟蹤
sched_get_priority_max 取得靜態(tài)優(yōu)先級(jí)的上限
sched_get_priority_min 取得靜態(tài)優(yōu)先級(jí)的下限
sched_getparam 取得進(jìn)程的調(diào)度參數(shù)
sched_getscheduler 取得指定進(jìn)程的調(diào)度策略
sched_rr_get_interval 取得按RR算法調(diào)度的實(shí)時(shí)進(jìn)程的時(shí)間片長度
sched_setparam 設(shè)置進(jìn)程的調(diào)度參數(shù)
sched_setscheduler 設(shè)置指定進(jìn)程的調(diào)度策略和參數(shù)
sched_yield 進(jìn)程主動(dòng)讓出處理器,并將自己等候調(diào)度隊(duì)列隊(duì)尾
vfork 創(chuàng)建一個(gè)子進(jìn)程,以供執(zhí)行新程序,常與execve等同時(shí)使用
wait 等待子進(jìn)程終止
wait3 參見wait
waitpid 等待指定子進(jìn)程終止
wait4 參見waitpid
capget 獲取進(jìn)程權(quán)限
capset 設(shè)置進(jìn)程權(quán)限
getsid 獲取會(huì)晤標(biāo)識(shí)號(hào)
setsid 設(shè)置會(huì)晤標(biāo)識(shí)號(hào)
· 文件系統(tǒng)控制
1.文件讀寫操作
fcntl 文件控制
open 打開文件
creat 創(chuàng)建新文件
close 關(guān)閉文件描述字
read 讀文件
write 寫文件
readv 從文件讀入數(shù)據(jù)到緩沖數(shù)組中
writev 將緩沖數(shù)組里的數(shù)據(jù)寫入文件
pread 對文件隨機(jī)讀
pwrite 對文件隨機(jī)寫
lseek 移動(dòng)文件指針
_llseek 在64位地址空間里移動(dòng)文件指針
dup 復(fù)制已打開的文件描述字
dup2 按指定條件復(fù)制文件描述字
flock 文件加/解鎖
poll I/O多路轉(zhuǎn)換
truncate 截?cái)辔募?/p>
ftruncate 參見truncate
umask 設(shè)置文件權(quán)限掩碼
fsync 把文件在內(nèi)存中的部分寫回磁盤
2.文件系統(tǒng)操作
access 確定文件的可存取性
chdir 改變當(dāng)前工作目錄
fchdir 參見chdir
chmod 改變文件方式
fchmod 參見chmod
chown 改變文件的屬主或用戶組
fchown 參見chown
lchown 參見chown
chroot 改變根目錄
stat 取文件狀態(tài)信息
lstat 參見stat
fstat 參見stat
statfs 取文件系統(tǒng)信息
fstatfs 參見statfs
readdir 讀取目錄項(xiàng)
getdents 讀取目錄項(xiàng)
mkdir 創(chuàng)建目錄
mknod 創(chuàng)建索引節(jié)點(diǎn)
rmdir 刪除目錄
rename 文件改名
link 創(chuàng)建鏈接
symlink 創(chuàng)建符號(hào)鏈接
unlink 刪除鏈接
readlink 讀符號(hào)鏈接的值
mount 安裝文件系統(tǒng)
umount 卸下文件系統(tǒng)
ustat 取文件系統(tǒng)信息
utime 改變文件的訪問修改時(shí)間
utimes 參見utime
quotactl 控制磁盤配額
· 系統(tǒng)控制
ioctl I/O總控制函數(shù)
_sysctl 讀/寫系統(tǒng)參數(shù)
acct 啟用或禁止進(jìn)程記賬
getrlimit 獲取系統(tǒng)資源上限
setrlimit 設(shè)置系統(tǒng)資源上限
getrusage 獲取系統(tǒng)資源使用情況
uselib 選擇要使用的二進(jìn)制函數(shù)庫
ioperm 設(shè)置端口I/O權(quán)限
iopl 改變進(jìn)程I/O權(quán)限級(jí)別
outb 低級(jí)端口操作
reboot 重新啟動(dòng)
swapon 打開交換文件和設(shè)備
swapoff 關(guān)閉交換文件和設(shè)備
bdflush 控制bdflush守護(hù)進(jìn)程
sysfs 取核心支持的文件系統(tǒng)類型
sysinfo 取得系統(tǒng)信息
adjtimex 調(diào)整系統(tǒng)時(shí)鐘
alarm 設(shè)置進(jìn)程的鬧鐘
getitimer 獲取計(jì)時(shí)器值
setitimer 設(shè)置計(jì)時(shí)器值
gettimeofday 取時(shí)間和時(shí)區(qū)
settimeofday 設(shè)置時(shí)間和時(shí)區(qū)
stime 設(shè)置系統(tǒng)日期和時(shí)間
time 取得系統(tǒng)時(shí)間
times 取進(jìn)程運(yùn)行時(shí)間
uname 獲取當(dāng)前UNIX系統(tǒng)的名稱、版本和主機(jī)等信息
vhangup 掛起當(dāng)前終端
nfsservctl 對NFS守護(hù)進(jìn)程進(jìn)行控制
vm86 進(jìn)入模擬8086模式
create_module 創(chuàng)建可裝載的模塊項(xiàng)
delete_module 刪除可裝載的模塊項(xiàng)
init_module 初始化模塊
query_module 查詢模塊信息
*get_kernel_syms 取得核心符號(hào),已被query_module代替
· 內(nèi)存管理
brk 改變數(shù)據(jù)段空間的分配
sbrk 參見brk
mlock 內(nèi)存頁面加鎖
munlock 內(nèi)存頁面解鎖
mlockall 調(diào)用進(jìn)程所有內(nèi)存頁面加鎖
munlockall 調(diào)用進(jìn)程所有內(nèi)存頁面解鎖
mmap 映射虛擬內(nèi)存頁
munmap 去除內(nèi)存頁映射
mremap 重新映射虛擬內(nèi)存地址
msync 將映射內(nèi)存中的數(shù)據(jù)寫回磁盤
mprotect 設(shè)置內(nèi)存映像保護(hù)
getpagesize 獲取頁面大小
sync 將內(nèi)存緩沖區(qū)數(shù)據(jù)寫回硬盤
cacheflush 將指定緩沖區(qū)中的內(nèi)容寫回磁盤
· 網(wǎng)絡(luò)管理
getdomainname 取域名
setdomainname 設(shè)置域名
gethostid 獲取主機(jī)標(biāo)識(shí)號(hào)
sethostid 設(shè)置主機(jī)標(biāo)識(shí)號(hào)
gethostname 獲取本主機(jī)名稱
sethostname 設(shè)置主機(jī)名稱
· socket控制
socketcall socket系統(tǒng)調(diào)用
socket 建立socket
bind 綁定socket到端口
connect 連接遠(yuǎn)程主機(jī)
accept 響應(yīng)socket連接請求
send 通過socket發(fā)送信息
sendto 發(fā)送UDP信息
sendmsg 參見send
recv 通過socket接收信息
recvfrom 接收UDP信息
recvmsg 參見recv
listen 監(jiān)聽socket端口
select 對多路同步I/O進(jìn)行輪詢
shutdown 關(guān)閉socket上的連接
getsockname 取得本地socket名字
getpeername 獲取通信對方的socket名字
getsockopt 取端口設(shè)置
setsockopt 設(shè)置端口參數(shù)
sendfile 在文件或端口間傳輸數(shù)據(jù)
socketpair 創(chuàng)建一對已聯(lián)接的無名socket
· 用戶管理
getuid 獲取用戶標(biāo)識(shí)號(hào)
setuid 設(shè)置用戶標(biāo)志號(hào)
getgid 獲取組標(biāo)識(shí)號(hào)
setgid 設(shè)置組標(biāo)志號(hào)
getegid 獲取有效組標(biāo)識(shí)號(hào)
setegid 設(shè)置有效組標(biāo)識(shí)號(hào)
geteuid 獲取有效用戶標(biāo)識(shí)號(hào)
seteuid 設(shè)置有效用戶標(biāo)識(shí)號(hào)
setregid 分別設(shè)置真實(shí)和有效的的組標(biāo)識(shí)號(hào)
setreuid 分別設(shè)置真實(shí)和有效的用戶標(biāo)識(shí)號(hào)
getresgid 分別獲取真實(shí)的,有效的和保存過的組標(biāo)識(shí)號(hào)
setresgid 分別設(shè)置真實(shí)的,有效的和保存過的組標(biāo)識(shí)號(hào)
getresuid 分別獲取真實(shí)的,有效的和保存過的用戶標(biāo)識(shí)號(hào)
setresuid 分別設(shè)置真實(shí)的,有效的和保存過的用戶標(biāo)識(shí)號(hào)
setfsgid 設(shè)置文件系統(tǒng)檢查時(shí)使用的組標(biāo)識(shí)號(hào)
setfsuid 設(shè)置文件系統(tǒng)檢查時(shí)使用的用戶標(biāo)識(shí)號(hào)
getgroups 獲取后補(bǔ)組標(biāo)志清單
setgroups 設(shè)置后補(bǔ)組標(biāo)志清單
· 進(jìn)程間通信
ipc 進(jìn)程間通信總控制調(diào)用
信號(hào)
sigaction 設(shè)置對指定信號(hào)的處理方法
sigprocmask 根據(jù)參數(shù)對信號(hào)集中的信號(hào)執(zhí)行阻塞/解除阻塞等操作
sigpending 為指定的被阻塞信號(hào)設(shè)置隊(duì)列
sigsuspend 掛起進(jìn)程等待特定信號(hào)
signal 參見signal
kill 向進(jìn)程或進(jìn)程組發(fā)信號(hào)
*sigblock 向被阻塞信號(hào)掩碼中添加信號(hào),已被sigprocmask代替
*siggetmask 取得現(xiàn)有阻塞信號(hào)掩碼,已被sigprocmask代替
*sigsetmask 用給定信號(hào)掩碼替換現(xiàn)有阻塞信號(hào)掩碼,已被sigprocmask代替
*sigmask 將給定的信號(hào)轉(zhuǎn)化為掩碼,已被sigprocmask代替
*sigpause 作用同sigsuspend,已被sigsuspend代替
sigvec 為兼容BSD而設(shè)的信號(hào)處理函數(shù),作用類似sigaction
ssetmask ANSI C的信號(hào)處理函數(shù),作用類似sigaction
消息
msgctl 消息控制操作
msgget 獲取消息隊(duì)列
msgsnd 發(fā)消息
msgrcv 取消息
管道
pipe 創(chuàng)建管道
信號(hào)量
semctl 信號(hào)量控制
semget 獲取一組信號(hào)量
semop 信號(hào)量操作
共享內(nèi)存
shmctl 控制共享內(nèi)存
shmget 獲取共享內(nèi)存
shmat 連接共享內(nèi)存
shmdt 拆卸共享內(nèi)存
-
Linux
+關(guān)注
關(guān)注
87文章
11345瀏覽量
210398 -
系統(tǒng)調(diào)用
+關(guān)注
關(guān)注
0文章
28瀏覽量
8356
原文標(biāo)題:若想成為一名Linux下編程高手,必須能對各種系統(tǒng)調(diào)用有透徹的了解
文章出處:【微信號(hào):mcuworld,微信公眾號(hào):嵌入式資訊精選】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評(píng)論請先 登錄
相關(guān)推薦
評(píng)論