最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解linux系統(tǒng)調(diào)用原理

 更新時(shí)間:2018年08月07日 08:31:16   投稿:laozhang  
這篇文章給大家詳細(xì)講述了linux系統(tǒng)調(diào)用原理的相關(guān)知識(shí)點(diǎn)內(nèi)容,對(duì)此有興趣的朋友參考學(xué)習(xí)下。

操作系統(tǒng)通過系統(tǒng)調(diào)用為運(yùn)行于其上的進(jìn)程提供服務(wù)。

當(dāng)用戶態(tài)進(jìn)程發(fā)起一個(gè)系統(tǒng)調(diào)用, CPU 將切換到 內(nèi)核態(tài) 并開始執(zhí)行一個(gè) 內(nèi)核函數(shù) 。 內(nèi)核函數(shù)負(fù)責(zé)響應(yīng)應(yīng)用程序的要求,例如操作文件、進(jìn)行網(wǎng)絡(luò)通訊或者申請(qǐng)內(nèi)存資源等。

舉一個(gè)最簡(jiǎn)單的例子,應(yīng)用進(jìn)程需要輸出一行文字,需要調(diào)用 write 這個(gè)系統(tǒng)調(diào)用:

hello_world.c

#include <string.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
 char *msg = "Hello, world!\n";
 write(1, msg, strlen(msg));

 return 0;
}

注解

讀者可能會(huì)有些疑問——輸出文本不是用 printf 等函數(shù)嗎?

確實(shí)是。 printf 是更高層次的庫(kù)函數(shù),建立在系統(tǒng)調(diào)用之上,實(shí)現(xiàn)數(shù)據(jù)格式化等功能。 因此,本質(zhì)上還是系統(tǒng)調(diào)用起決定性作用。

調(diào)用流程

那么,在應(yīng)用程序內(nèi),調(diào)用一個(gè)系統(tǒng)調(diào)用的流程是怎樣的呢?

我們以一個(gè)假設(shè)的系統(tǒng)調(diào)用 xyz 為例,介紹一次系統(tǒng)調(diào)用的所有環(huán)節(jié)。

如上圖,系統(tǒng)調(diào)用執(zhí)行的流程如下:

  • 應(yīng)用程序 代碼調(diào)用系統(tǒng)調(diào)用( xyz ),該函數(shù)是一個(gè)包裝系統(tǒng)調(diào)用的 庫(kù)函數(shù) ;
  • 庫(kù)函數(shù) ( xyz )負(fù)責(zé)準(zhǔn)備向內(nèi)核傳遞的參數(shù),并觸發(fā) 軟中斷 以切換到內(nèi)核;
  • CPU 被 軟中斷 打斷后,執(zhí)行 中斷處理函數(shù) ,即 系統(tǒng)調(diào)用處理函數(shù) ( system_call );
  • 系統(tǒng)調(diào)用處理函數(shù) 調(diào)用 系統(tǒng)調(diào)用服務(wù)例程 ( sys_xyz ),真正開始處理該系統(tǒng)調(diào)用;

執(zhí)行態(tài)切換

應(yīng)用程序 ( application program )與 庫(kù)函數(shù) ( libc )之間, 系統(tǒng)調(diào)用處理函數(shù) ( system call handler )與 系統(tǒng)調(diào)用服務(wù)例程 ( system call service routine )之間, 均是普通函數(shù)調(diào)用,應(yīng)該不難理解。 而 庫(kù)函數(shù) 與 系統(tǒng)調(diào)用處理函數(shù) 之間,由于涉及用戶態(tài)與內(nèi)核態(tài)的切換,要復(fù)雜一些。

Linux 通過 軟中斷 實(shí)現(xiàn)從 用戶態(tài) 到 內(nèi)核態(tài) 的切換。 用戶態(tài) 與 內(nèi)核態(tài) 是獨(dú)立的執(zhí)行流,因此在切換時(shí),需要準(zhǔn)備 執(zhí)行棧 并保存 寄存器 。

內(nèi)核實(shí)現(xiàn)了很多不同的系統(tǒng)調(diào)用(提供不同功能),而 系統(tǒng)調(diào)用處理函數(shù) 只有一個(gè)。 因此,用戶進(jìn)程必須傳遞一個(gè)參數(shù)用于區(qū)分,這便是 系統(tǒng)調(diào)用號(hào) ( system call number )。 在 Linux 中, 系統(tǒng)調(diào)用號(hào) 一般通過 eax 寄存器 來傳遞。

總結(jié)起來, 執(zhí)行態(tài)切換 過程如下:

  • 應(yīng)用程序 在 用戶態(tài) 準(zhǔn)備好調(diào)用參數(shù),執(zhí)行 int 指令觸發(fā) 軟中斷 ,中斷號(hào)為 0x80 ;
  • CPU 被軟中斷打斷后,執(zhí)行對(duì)應(yīng)的 中斷處理函數(shù) ,這時(shí)便已進(jìn)入 內(nèi)核態(tài) ;
  • 系統(tǒng)調(diào)用處理函數(shù) 準(zhǔn)備 內(nèi)核執(zhí)行棧 ,并保存所有 寄存器 (一般用匯編語(yǔ)言實(shí)現(xiàn));
  • 系統(tǒng)調(diào)用處理函數(shù) 根據(jù) 系統(tǒng)調(diào)用號(hào) 調(diào)用對(duì)應(yīng)的 C 函數(shù)—— 系統(tǒng)調(diào)用服務(wù)例程 ;
  • 系統(tǒng)調(diào)用處理函數(shù) 準(zhǔn)備 返回值 并從 內(nèi)核棧 中恢復(fù) 寄存器 ;
  • 系統(tǒng)調(diào)用處理函數(shù) 執(zhí)行 ret 指令切換回 用戶態(tài) ;

編程實(shí)踐

下面,通過一個(gè)簡(jiǎn)單的程序,看看應(yīng)用程序如何在 用戶態(tài) 準(zhǔn)備參數(shù)并通過 int 指令觸發(fā) 軟中斷 以陷入 內(nèi)核態(tài) 執(zhí)行 系統(tǒng)調(diào)用 :

hello_world-int.S

.section .rodata

msg:
 .ascii "Hello, world!\n"

.section .text

.global _start

_start:
 # call SYS_WRITE
 movl $4, %eax
 # push arguments
 movl $1, %ebx
 movl $msg, %ecx
 movl $14, %edx
 int $0x80

 # Call SYS_EXIT
 movl $1, %eax
 # push arguments
 movl $0, %ebx
 # initiate
 int $0x80

這是一個(gè)匯編語(yǔ)言程序,程序入口在 _start 標(biāo)簽之后。

第 12 行,準(zhǔn)備 系統(tǒng)調(diào)用號(hào) :將常數(shù) 4 放進(jìn) 寄存器 eax 。 系統(tǒng)調(diào)用號(hào) 4 代表 系統(tǒng)調(diào)用 SYS_write , 我們將通過該系統(tǒng)調(diào)用向標(biāo)準(zhǔn)輸出寫入一個(gè)字符串。

第 14-16 行, 準(zhǔn)備系統(tǒng)調(diào)用參數(shù):第一個(gè)參數(shù)放進(jìn) 寄存器 ebx ,第二個(gè)參數(shù)放進(jìn) ecx , 以此類推。

write 系統(tǒng)調(diào)用需要 3 個(gè)參數(shù):

  • 文件描述符 ,標(biāo)準(zhǔn)輸出文件描述符為 1 ;
  • 寫入內(nèi)容(緩沖區(qū))地址;
  • 寫入內(nèi)容長(zhǎng)度(字節(jié)數(shù));

第 17 行,執(zhí)行 int 指令觸發(fā)軟中斷 0x80 ,程序?qū)⑾萑雰?nèi)核態(tài)并由內(nèi)核執(zhí)行系統(tǒng)調(diào)用。 系統(tǒng)調(diào)用執(zhí)行完畢后,內(nèi)核將負(fù)責(zé)切換回用戶態(tài),應(yīng)用程序繼續(xù)執(zhí)行之后的指令( 從 20 行開始 )。

第 20-24 行,調(diào)用 exit 系統(tǒng)調(diào)用,以便退出程序。

注解
注意到,這里必須顯式調(diào)用 exit 系統(tǒng)調(diào)用退出程序。 否則,程序?qū)⒗^續(xù)往下執(zhí)行,最終遇到段錯(cuò)誤( segmentation fault )!

讀者可能很好奇——我在寫 C 語(yǔ)言或者其他程序時(shí),這個(gè)調(diào)用并不是必須的!

這是因?yàn)?C 庫(kù)( libc )已經(jīng)幫你把臟活累活都干了。

接下來,我們編譯并執(zhí)行這個(gè)匯編語(yǔ)言程序:

$ ls
hello_world-int.S
$ as -o hello_world-int.o hello_world-int.S
$ ls
hello_world-int.o hello_world-int.S
$ ld -o hello_world-int hello_world-int.o
$ ls
hello_world-int hello_world-int.o hello_world-int.S
$ ./hello_world-int
Hello, world!

其實(shí),將 系統(tǒng)調(diào)用號(hào) 和 調(diào)用參數(shù) 放進(jìn)正確的 寄存器 并觸發(fā)正確的 軟中斷 是個(gè)重復(fù)的麻煩事。 C 庫(kù)已經(jīng)把這臟累活給干了——試試 syscall 函數(shù)吧!

hello_world-syscall.c

#include <string.h>
#include <sys/syscall.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
 char *msg = "Hello, world!\n";
 syscall(SYS_write, 1, msg, strlen(msg));

 return 0;
}

相關(guān)文章

  • centOS7.4 安裝 mysql 5.7.26的教程詳解

    centOS7.4 安裝 mysql 5.7.26的教程詳解

    CentOS中默認(rèn)安裝有MariaDB,這個(gè)是MySQL的分支,但為了需要,還是要在系統(tǒng)中安裝MySQL,而且安裝完成之后可以直接覆蓋掉MariaDB。這篇文章主要介紹了centOS7.4 安裝 mysql 5.7.26,需要的朋友可以參考下
    2019-06-06
  • linux安裝Jenkins超詳細(xì)全過程

    linux安裝Jenkins超詳細(xì)全過程

    大家好,本篇文章主要講的是linux安裝Jenkins超詳細(xì)全過程,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • 在lnmp環(huán)境中的nginx編譯安裝

    在lnmp環(huán)境中的nginx編譯安裝

    本篇文章給大家分享了在lnmp環(huán)境中的nginx編譯安裝的相關(guān)步驟以及需要注意的地方,有興趣的朋友參考學(xué)習(xí)下。
    2018-04-04
  • 淺談Linux vfork與fork簡(jiǎn)單對(duì)比分析

    淺談Linux vfork與fork簡(jiǎn)單對(duì)比分析

    本篇文章主要介紹了淺談Linux vfork與fork簡(jiǎn)單對(duì)比分析,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-12-12
  • Linux如何更改用戶名或密碼

    Linux如何更改用戶名或密碼

    這篇文章主要介紹了Linux如何更改用戶名或密碼問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Ubuntu掛載3T硬盤或大于2T磁盤的方法

    Ubuntu掛載3T硬盤或大于2T磁盤的方法

    本篇文章主要介紹了Ubuntu掛載3T硬盤或大于2T磁盤的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-03-03
  • KLOXO重置管理員登陸密碼的方法分享

    KLOXO重置管理員登陸密碼的方法分享

    今天準(zhǔn)備整理面板的配置問題的,登陸密碼忘記了,郁悶不已。我們只有通過SSH來重置KLOXO初始密碼
    2012-09-09
  • Thrift的安裝方法和簡(jiǎn)單實(shí)例

    Thrift的安裝方法和簡(jiǎn)單實(shí)例

    下面小編就為大家?guī)硪黄猅hrift的安裝方法和簡(jiǎn)單實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-12-12
  • linux實(shí)現(xiàn)除了某個(gè)文件或某個(gè)文件夾以外的全部刪除

    linux實(shí)現(xiàn)除了某個(gè)文件或某個(gè)文件夾以外的全部刪除

    下面小編就為大家?guī)硪黄猯inux實(shí)現(xiàn)除了某個(gè)文件或某個(gè)文件夾以外的全部刪除。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-12-12
  • grub損壞,開機(jī)出現(xiàn)GRUB 2 啟動(dòng)提示符的解決方法

    grub損壞,開機(jī)出現(xiàn)GRUB 2 啟動(dòng)提示符的解決方法

    下面小編就為大家?guī)硪黄猤rub損壞,開機(jī)出現(xiàn)GRUB 2 啟動(dòng)提示符的解決方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-12-12

最新評(píng)論

岳普湖县| 盘锦市| 友谊县| 东兴市| 武功县| 手游| 石楼县| 西贡区| 高州市| 忻城县| 瑞安市| 成安县| 梧州市| 苏尼特左旗| 雷波县| 涟水县| 秦皇岛市| 晋中市| 西畴县| 富阳市| 安乡县| 子洲县| 宁阳县| 上虞市| 广东省| 金溪县| 龙里县| 白河县| 通辽市| 伊宁县| 灵武市| 阿坝县| 平果县| 德安县| 剑河县| 天台县| 扎赉特旗| 光山县| 托克逊县| 巴楚县| 玉林市|