<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      《Linux內(nèi)核設(shè)計(jì)與實(shí)現(xiàn)》讀書(shū)筆記(五)- 系統(tǒng)調(diào)用

      主要內(nèi)容:

      1. 什么是系統(tǒng)調(diào)用
      2. Linux上的系統(tǒng)調(diào)用實(shí)現(xiàn)原理
      3. 一個(gè)簡(jiǎn)單的系統(tǒng)調(diào)用的實(shí)現(xiàn)

      1. 什么是系統(tǒng)調(diào)用

      簡(jiǎn)單來(lái)說(shuō),系統(tǒng)調(diào)用就是用戶程序和硬件設(shè)備之間的橋梁。

      用戶程序在需要的時(shí)候,通過(guò)系統(tǒng)調(diào)用來(lái)使用硬件設(shè)備。

      系統(tǒng)調(diào)用的存在,有以下重要的意義:

      1)用戶程序通過(guò)系統(tǒng)調(diào)用來(lái)使用硬件,而不用關(guān)心具體的硬件設(shè)備,這樣大大簡(jiǎn)化了用戶程序的開(kāi)發(fā)。

          比如:用戶程序通過(guò)write()系統(tǒng)調(diào)用就可以將數(shù)據(jù)寫(xiě)入文件,而不必關(guān)心文件是在磁盤(pán)上還是軟盤(pán)上,或者其他存儲(chǔ)上。

      2)系統(tǒng)調(diào)用使得用戶程序有更好的可移植性。

          只要操作系統(tǒng)提供的系統(tǒng)調(diào)用接口相同,用戶程序就可在不用修改的情況下,從一個(gè)系統(tǒng)遷移到另一個(gè)操作系統(tǒng)。

      3)系統(tǒng)調(diào)用使得內(nèi)核能更好的管理用戶程序,增強(qiáng)了系統(tǒng)的穩(wěn)定性。

          因?yàn)橄到y(tǒng)調(diào)用是內(nèi)核實(shí)現(xiàn)的,內(nèi)核通過(guò)系統(tǒng)調(diào)用來(lái)控制開(kāi)放什么功能及什么權(quán)限給用戶程序。

          這樣可以避免用戶程序不正確的使用硬件設(shè)備,從而破壞了其他程序。

      4)系統(tǒng)調(diào)用有效的分離了用戶程序和內(nèi)核的開(kāi)發(fā)。

          用戶程序只需關(guān)心系統(tǒng)調(diào)用API,通過(guò)這些API來(lái)開(kāi)發(fā)自己的應(yīng)用,不用關(guān)心API的具體實(shí)現(xiàn)。

          內(nèi)核則只要關(guān)心系統(tǒng)調(diào)用API的實(shí)現(xiàn),而不必管它們是被如何調(diào)用的。

       

      用戶程序,系統(tǒng)調(diào)用,內(nèi)核,硬件設(shè)備的調(diào)用關(guān)系如下圖:

      image

       

      2. Linux上的系統(tǒng)調(diào)用實(shí)現(xiàn)原理

      要想實(shí)現(xiàn)系統(tǒng)調(diào)用,主要實(shí)現(xiàn)以下幾個(gè)方面:

      1. 通知內(nèi)核調(diào)用一個(gè)哪個(gè)系統(tǒng)調(diào)用
      2. 用戶程序把系統(tǒng)調(diào)用的參數(shù)傳遞給內(nèi)核
      3. 用戶程序獲取內(nèi)核返回的系統(tǒng)調(diào)用返回值

      下面看看Linux是如何實(shí)現(xiàn)上面3個(gè)功能的。

      2.1 通知內(nèi)核調(diào)用一個(gè)哪個(gè)系統(tǒng)調(diào)用

      每個(gè)系統(tǒng)調(diào)用都有一個(gè)系統(tǒng)調(diào)用號(hào),系統(tǒng)調(diào)用發(fā)生時(shí),內(nèi)核就是根據(jù)傳入的系統(tǒng)調(diào)用號(hào)來(lái)知道是哪個(gè)系統(tǒng)調(diào)用的。

      在x86架構(gòu)中,用戶空間將系統(tǒng)調(diào)用號(hào)是放在eax中的,系統(tǒng)調(diào)用處理程序通過(guò)eax取得系統(tǒng)調(diào)用號(hào)。

      系統(tǒng)調(diào)用號(hào)定義在內(nèi)核代碼:arch/alpha/include/asm/unistd.h 中,可以看出linux的系統(tǒng)調(diào)用不是很多。

      2.2 用戶程序把系統(tǒng)調(diào)用的參數(shù)傳遞給內(nèi)核

      系統(tǒng)調(diào)用的參數(shù)也是通過(guò)寄存器傳給內(nèi)核的,在x86系統(tǒng)上,系統(tǒng)調(diào)用的前5個(gè)參數(shù)放在ebx,ecx,edx,esi和edi中,如果參數(shù)多的話,還需要用個(gè)單獨(dú)的寄存器存放指向所有參數(shù)在用戶空間地址的指針。

      一般的系統(tǒng)調(diào)用都是通過(guò)C庫(kù)(最常用的是glibc庫(kù))來(lái)訪問(wèn)的,Linux內(nèi)核提供一個(gè)從用戶程序直接訪問(wèn)系統(tǒng)調(diào)用的方法。

      參見(jiàn)內(nèi)核代碼:arch/cris/include/arch-v10/arch/unistd.h

      里面定義了6個(gè)宏,分別可以調(diào)用參數(shù)個(gè)數(shù)為0~6的系統(tǒng)調(diào)用

      _syscall0(type,name)
      _syscall1(type,name,type1,arg1)
      _syscall2(type,name,type1,arg1,type2,arg2)
      _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)
      _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)
      _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5)
      _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6)

      超過(guò)6個(gè)參數(shù)的系統(tǒng)調(diào)用很罕見(jiàn),所以這里只定義了6個(gè)。

      2.3 用戶程序獲取內(nèi)核返回的系統(tǒng)調(diào)用返回值

      獲取系統(tǒng)調(diào)用的返回值也是通過(guò)寄存器,在x86系統(tǒng)上,返回值放在eax中。

       

      3. 一個(gè)簡(jiǎn)單的系統(tǒng)調(diào)用的實(shí)現(xiàn)

      了解了Linux上系統(tǒng)調(diào)用的原理,下面就可以自己來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的系統(tǒng)調(diào)用。

      3.1 環(huán)境準(zhǔn)備

      為了不破壞現(xiàn)有系統(tǒng),我是用虛擬機(jī)來(lái)實(shí)驗(yàn)的。

      主機(jī):fedora16 x86_64系統(tǒng) + kvm(一種虛擬技術(shù),就像virtualbox,vmware等)

      虛擬機(jī): 也是安裝fedora16 x86_64系統(tǒng)(通過(guò)virt-manager很容易安裝一個(gè)系統(tǒng))

       

      下載內(nèi)核源碼:www.kernel.org  下載最新的就行

       

      3.2 修改內(nèi)核源碼中的相應(yīng)文件

      主要修改以下文件:

      arch/x86/ia32/ia32entry.S
      arch/x86/include/asm/unistd_32.h
      arch/x86/include/asm/unistd_64.h
      arch/x86/kernel/syscall_table_32.S
      include/asm-generic/unistd.h
      include/linux/syscalls.h
      kernel/sys.c

      我在sys.c中追加了2個(gè)函數(shù):sys_foo和sys_bar

      如果是在x86_64的內(nèi)核中增加一個(gè)系統(tǒng)調(diào)用,只需修改 arch/x86/include/asm/unistd_64.h,比如sys_bar。

      修改內(nèi)容參見(jiàn)下面的diff文件:

      diff -r new/arch/x86/ia32/ia32entry.S old/arch/x86/ia32/ia32entry.S
      855d854
      <     .quad sys_foo
      diff -r new/arch/x86/include/asm/unistd_32.h old/arch/x86/include/asm/unistd_32.h
      357d356
      < #define __NR_foo    349
      361c360
      < #define NR_syscalls 350
      ---
      > #define NR_syscalls 349
      diff -r new/arch/x86/include/asm/unistd_64.h old/arch/x86/include/asm/unistd_64.h
      689,692d688
      < #define __NR_foo            312
      < __SYSCALL(__NR_foo, sys_foo)
      < #define __NR_bar            313
      < __SYSCALL(__NR_bar, sys_bar)
      diff -r new/arch/x86/kernel/syscall_table_32.S old/arch/x86/kernel/syscall_table_32.S
      351d350
      <     .long sys_foo
      diff -r new/include/asm-generic/unistd.h old/include/asm-generic/unistd.h
      694,695d693
      < #define __NR_foo 272
      < __SYSCALL(__NR_foo, sys_foo)
      698c696
      < #define __NR_syscalls 273
      ---
      > #define __NR_syscalls 272
      diff -r new/kernel/sys.c old/kernel/sys.c
      1920,1928d1919
      < 
      < asmlinkage long sys_foo(void)
      < {
      <     return 1112223334444555;
      < }
      < asmlinkage long sys_bar(void)
      < {
      <     return 1234567890;
      < }

       

      3.3 編譯內(nèi)核

      #cd linux-3.2.28
      #make menuconfig  (選擇要編譯參數(shù),如果不熟悉內(nèi)核編譯,用默認(rèn)選項(xiàng)即可)
      #make all  (這一步真的時(shí)間很長(zhǎng)......)
      #make modules_install
      #make install  (這一步會(huì)把新的內(nèi)核加到啟動(dòng)項(xiàng)中)
      #reboot  (重啟系統(tǒng)進(jìn)入新的內(nèi)核)

       

      3.4 編寫(xiě)調(diào)用的系統(tǒng)調(diào)用的代碼

      #include <unistd.h>
      #include <sys/syscall.h>
      #include <string.h>
      #include <stdio.h>
      #include <errno.h>
      
      
      #define __NR_foo 312
      #define __NR_bar 313
      
      int main()
      {
              printf ("result foo is %ld\n", syscall(__NR_foo));
              printf("%s\n", strerror(errno));
              printf ("result bar is %ld\n", syscall(__NR_bar));
              printf("%s\n", strerror(errno));
              return 0;
      }

      編譯運(yùn)行上面的代碼:

      #gcc test.c -o test
      #./test

      運(yùn)行結(jié)果如下:

      result foo is 1112223334444555
      Success
      result bar is 1234567890
      Success
      posted @ 2012-09-17 09:58  wang_yb  閱讀(13150)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 国产精品中文字幕在线| 国内精品自国内精品自久久| 亚洲第一精品一二三区| 天美传媒xxxxhd videos3| 亚洲精品欧美综合二区| 精品国产不卡在线观看免费 | 出国| 综合色一色综合久久网| 成人网站免费观看永久视频下载| 美女无遮挡免费视频网站| 亚洲国产精品综合久久网络| 成人一区二区不卡国产| 久久精品夜夜夜夜夜久久| 亚洲人成色99999在线观看| 精品 日韩 国产 欧美 视频| 激情综合五月网| 影视先锋av资源噜噜| 丁香五月婷激情综合第九色| 欧美精品亚洲精品日韩专区| 日本免费观看mv免费版视频网站| 成人区人妻精品一区二区 | 在国产线视频A在线视频| 亚洲熟妇丰满多毛xxxx| 国产欧美精品一区二区三区-老狼| 亚洲一区二区三区蜜桃臀| 无码国内精品久久人妻蜜桃| 亚洲熟妇av一区二区三区宅男| 亚洲av与日韩av在线| 亚洲精品天堂一区二区| 日日摸天天爽天天爽视频| 国产高清视频一区二区三区| 噜噜噜噜私人影院| 国产激情免费视频在线观看| 91精品国产免费人成网站| 亚洲综合天堂一区二区三区| 四虎成人高清永久免费看| 日韩最新中文字幕| 少妇人妻偷人精品无码视频| 亚洲日韩久热中文字幕| 仙桃市| 国产一区二区三区AV在线无码观看|