操作系統(tǒng)課設(shè)_第1頁
操作系統(tǒng)課設(shè)_第2頁
操作系統(tǒng)課設(shè)_第3頁
操作系統(tǒng)課設(shè)_第4頁
操作系統(tǒng)課設(shè)_第5頁
已閱讀5頁,還剩40頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、課課 程程 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告課程名稱課程名稱: 計(jì)算機(jī)操作系統(tǒng)專業(yè)班級(jí):專業(yè)班級(jí): 學(xué)學(xué) 號(hào):號(hào): 姓姓 名:名: 指導(dǎo)教師:指導(dǎo)教師: 報(bào)告日期:報(bào)告日期: 計(jì)算機(jī)科學(xué)與技術(shù)學(xué)院計(jì)算機(jī)科學(xué)與技術(shù)學(xué)院I華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告目 錄1實(shí)驗(yàn)?zāi)康膶?shí)驗(yàn)?zāi)康?.22實(shí)驗(yàn)環(huán)境實(shí)驗(yàn)環(huán)境 .23實(shí)驗(yàn)內(nèi)容實(shí)驗(yàn)內(nèi)容 .23.1實(shí)驗(yàn)一.23.2實(shí)驗(yàn)二.23.3實(shí)驗(yàn)三.23.4實(shí)驗(yàn)四(選做).33.5實(shí)驗(yàn)五(選做).34設(shè)計(jì)與實(shí)現(xiàn)設(shè)計(jì)與實(shí)現(xiàn).34.1實(shí)驗(yàn)一.34.2實(shí)驗(yàn)二.104.3實(shí)驗(yàn)三.144.4實(shí)驗(yàn)四.205心得體會(huì)心得體會(huì) .432華華 中中 科科 技技

2、大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告1實(shí)驗(yàn)?zāi)康恼莆?Linux 操作系統(tǒng)的使用方法;了解 Linux 系統(tǒng)內(nèi)核代碼結(jié)構(gòu);掌握實(shí)例操作系統(tǒng)的實(shí)現(xiàn)方法;2實(shí)驗(yàn)環(huán)境本次課程設(shè)計(jì)采用的操作系統(tǒng)環(huán)境是 windows8、Ubuntu 雙系統(tǒng),Ubuntu 系統(tǒng)版本號(hào)為 14.04,內(nèi)核版本號(hào)為 linux 3.13.0;采用的編程環(huán)境為 CodeBlocks IDE 和QtCreator。3實(shí)驗(yàn)內(nèi)容3.1實(shí)驗(yàn)一掌握 Linux 操作系統(tǒng)的使用方法,包括鍵盤命令、系統(tǒng)調(diào)用;掌握在 Linux 下的編程環(huán)境。(1)編寫一個(gè) C 程序,其內(nèi)容為實(shí)現(xiàn)文件拷貝的功能。(2)編寫一個(gè) C 程序,其內(nèi)容為分

3、窗口同時(shí)顯示三個(gè)并發(fā)進(jìn)程的運(yùn)行結(jié)果。要求用到 Linux 下的圖形庫(GTK/Qt) 。3.2實(shí)驗(yàn)二掌握系統(tǒng)調(diào)用的實(shí)現(xiàn)過程,通過編譯內(nèi)核方法,增加一個(gè)新的系統(tǒng)調(diào)用,另編寫一個(gè)應(yīng)用程序,調(diào)用新增加的系統(tǒng)調(diào)用。實(shí)現(xiàn)的功能是:文件拷貝。3.3實(shí)驗(yàn)三掌握增加設(shè)備驅(qū)動(dòng)程序的方法。通過模塊方法,增加一個(gè)新的設(shè)備驅(qū)動(dòng)程序,其功能可以簡(jiǎn)單。 (實(shí)現(xiàn)字符設(shè)備的驅(qū)動(dòng))3華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告3.4實(shí)驗(yàn)四(選做)了解和掌握/proc 文件系統(tǒng)的特點(diǎn)和使用方法(1)了解/proc 文件的特點(diǎn)和使用方法;(2)監(jiān)控系統(tǒng)狀態(tài),顯示系統(tǒng)中若干部件使用狀態(tài);(3)用圖形界面實(shí)現(xiàn)

4、系統(tǒng)監(jiān)控狀態(tài);3.5實(shí)驗(yàn)五(選做)設(shè)計(jì)并實(shí)現(xiàn)一個(gè)模擬的文件系統(tǒng)。多用戶的多級(jí)目錄的文件系統(tǒng)設(shè)計(jì)。多用戶、多級(jí)目錄、login(用戶登錄) 、系統(tǒng)初始化(建文件卷,提供登錄模塊) 、文件的創(chuàng)建、文件的打開、文件的讀寫、文件關(guān)閉、刪除文件、創(chuàng)建目錄(建立子目錄) 、改變當(dāng)前目錄、列出文件目錄、退出。4設(shè)計(jì)與實(shí)現(xiàn)4.1實(shí)驗(yàn)一4.1.1 實(shí)驗(yàn)要求掌握 Linux 操作系統(tǒng)的使用方法,包括鍵盤命令、系統(tǒng)調(diào)用;掌握在 Linux 下的編程環(huán)境。4.1.2 具體實(shí)現(xiàn)本實(shí)驗(yàn)內(nèi)容是用 CodeBlocks IDE 實(shí)現(xiàn)的,該軟件整合了函數(shù)庫和編譯器,因此使用起來非常方便。(1)編寫一個(gè) C 程序,其內(nèi)容為實(shí)現(xiàn)文

5、件拷貝的功能。在 windows 操作系統(tǒng)上實(shí)現(xiàn)的文件拷貝功能一般使用 fopen、fread、fwrite 三個(gè)來自標(biāo)準(zhǔn) C 函數(shù)庫的函數(shù)執(zhí)行對(duì)文件的打開、讀、寫操作,而本次實(shí)驗(yàn)要求使用Linux 系統(tǒng)的系統(tǒng)調(diào)用 open、read、write 實(shí)現(xiàn)上述三個(gè)操作。用到的主要頭文件如下:4華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告stdio.h標(biāo)準(zhǔn)輸入輸出頭文件string.h字符串處理相關(guān)頭文件unistd.hLinux 系統(tǒng)調(diào)用頭文件,比如 read、writefcntl.h包含 open 系統(tǒng)調(diào)用errno.h包含一些調(diào)試錯(cuò)誤時(shí)用到的變量具體實(shí)現(xiàn)思路:打開兩個(gè)

6、文件(分別是源文件和目標(biāo)文件,可以是任意字符流形式存儲(chǔ)的文件,包括文本文件、照片等) ,調(diào)用 read 函數(shù)讀取源文件的內(nèi)容,將 read 的返回值作為while 循環(huán)的判斷條件,當(dāng)返回值大于 0(即還未讀取完畢源文件中的內(nèi)容)時(shí),調(diào)用 write 執(zhí)行向目標(biāo)文件寫的操作,否則跳出循環(huán),表示源文件已經(jīng)被拷貝到目標(biāo)文件,然后調(diào)用 close 關(guān)閉源文件和目標(biāo)文件。代碼編寫完成后,在 CodeBlocks 上編譯運(yùn)行即可。程序運(yùn)行之前,桌面上只有“教程.docx” ,運(yùn)行之后,桌面上新建了“教程副本.docx” ,并且“教程.docx”中的內(nèi)容被復(fù)制到了“教程副本.docx” ,程序運(yùn)行結(jié)果如下所

7、示:詳細(xì)代碼見 4.1.3。(2)編寫一個(gè) C 程序,其內(nèi)容為分窗口同時(shí)顯示三個(gè)并發(fā)進(jìn)程的運(yùn)行結(jié)果。要求用到 Linux 下的圖形庫(GTK/Qt) 。5華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告本次實(shí)驗(yàn)使用的圖形庫是跨平臺(tái)的開發(fā)工具 Qt。首先下載 Qt 的安裝包并安裝。Qt 安裝完之后,先新建一個(gè) Qt 控制臺(tái)應(yīng)用 MAIN 作為主進(jìn)程,用于調(diào)用三個(gè)并發(fā)的子進(jìn)程。在主進(jìn)程的 main 函數(shù)中,使用 fork 創(chuàng)建三個(gè)子進(jìn)程,若進(jìn)程創(chuàng)建成功(即 fork 函數(shù)返回值等于 0) ,則使用 execv 函數(shù)進(jìn)入對(duì)應(yīng)的子進(jìn)程(get、copy、put) 。主進(jìn)程程序編寫

8、完成后,再新建三個(gè) Qt Widgets Application,分別作為三個(gè)子進(jìn)程get、copy、put(所實(shí)現(xiàn)的功能并不是拷貝) 。由于三個(gè)子進(jìn)程窗口顯示的內(nèi)容形式一模一樣,所以以子進(jìn)程 get 為例。get 進(jìn)程的窗口顯示了一下四個(gè)內(nèi)容:當(dāng)前時(shí)間、子進(jìn)程名稱、子進(jìn)程的 pid 和父進(jìn)程 MAIN 的 pid。用 Qt 的對(duì)象 QDateTime 獲取系統(tǒng)當(dāng)前時(shí)間,然后將時(shí)間轉(zhuǎn)換成一個(gè)字符串寫在一個(gè) QLabel 類的實(shí)例中,然后將該實(shí)例添加至窗口;直接把當(dāng)前進(jìn)程名稱寫在一個(gè)標(biāo)簽上然后添加至窗口;使用 getpid和 getppid 函數(shù)分別獲取當(dāng)前進(jìn)程號(hào)和父進(jìn)程號(hào),然后調(diào)用 sprin

9、tf 把進(jìn)程號(hào)轉(zhuǎn)換成字符串類型之后寫在標(biāo)簽上并添加至窗口即可。主進(jìn)程和三個(gè)子進(jìn)程的程序全部編寫完后,直接在 Qt 上編譯運(yùn)行。程序運(yùn)行結(jié)果如下所示:6華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告詳細(xì)代碼見 4.1.3。7華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告4.1.3 源代碼(1) 文件拷貝源代碼#include #include #include #include #include #include #include #define SIZE 10 /每次讀取的字符數(shù)目char * srcFile=/home/ilbear/桌面/教程

10、.docx;char *goalFile=/home/ilbear/桌面/教程副本.docx;int main(int argc, const char *argv) int src, goal; int read_len; char buffSIZE; src=open(srcFile,O_RDONLY); if(src0) printf(Fail to open %sn.,srcFile); exit(1); goal=open(goalFile,O_WRONLY|O_CREAT,0666); if(goal0) write(goal,buff,read_len); close(src);

11、 close(goal); return 0;(2) 三個(gè)并發(fā)進(jìn)程#主進(jìn)程主進(jìn)程 MAIN#include #include #include #include #include #include int main(int argc, char *argv)8華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告 QCoreApplication a(argc, argv); pid_t p1,p2,p3; if(p1=fork()=0) execv(/home/ilbear/桌面/build-get-Desktop_Qt_5_4_1_GCC_64bit-Debug/get,N

12、ULL); else if(p2=fork()=0) execv(/home/ilbear/桌面/build-copy-Desktop_Qt_5_4_1_GCC_64bit-Debug/copy,NULL); else if( p3=fork()=0) execv(/home/ilbear/桌面/build-put-Desktop_Qt_5_4_1_GCC_64bit-Debug/put,NULL); waitpid(p1,NULL,0); waitpid(p2,NULL,0); waitpid(p3,NULL,0); return a.exec();#子進(jìn)程子進(jìn)程 getmainwindow

13、.cpp#include mainwindow.h#include ui_mainwindow.h#include #include #include #include MainWindow:MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui:MainWindow),sharememory1(share1) ui-setupUi(this); setWindowTitle(get); setWindowFlags(Qt:Dialog); move(0,0); resize(500,500); char str128,f_id

14、128; sprintf(str,%d,getpid(); sprintf(f_id,%d,getppid(); ui-textBrowser-setText(get); ui-textBrowser_2-setText(str); ui-textBrowser_3-setText(f_id); QTimer *timer = new QTimer(this); connect(timer, SIGNAL(timeout(), this, SLOT(timerUpDate();9華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告 timer-start(1);MainWin

15、dow:MainWindow() delete ui;void MainWindow:timerUpDate() QDateTime time = QDateTime:currentDateTime(); QString str = time.toString(yyyy-MM-dd hh:mm:ss dddd); ui-labelCurDate-setText(str);#子進(jìn)程子進(jìn)程 copymainwindow.cpp#include mainwindow.h#include ui_mainwindow.h#include #include #include #include MainWi

16、ndow:MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui:MainWindow),sharememory1(share1),sharememory2(share2) char str128,f_id128; ui-setupUi(this); setWindowTitle(copy); setWindowFlags(Qt:Dialog); move(500,500); resize(500,500); sprintf(str,%d,getpid(); sprintf(f_id,%d,getppid(); ui-textB

17、rowser-setText(copy); ui-textBrowser_2-setText(str); ui-textBrowser_3-setText(f_id); QTimer *timer = new QTimer(this); connect(timer, SIGNAL(timeout(), this, SLOT(timerUpDate(); timer-start(1);MainWindow:MainWindow() delete ui;void MainWindow:timerUpDate() QDateTime time = QDateTime:currentDateTime(

18、); QString str = time.toString(yyyy-MM-dd hh:mm:ss dddd); ui-labelCurDate-setText(str);#子進(jìn)程子進(jìn)程 putmainwindow.cpp#include mainwindow.h#include ui_mainwindow.h10華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告#include #include #include #include MainWindow:MainWindow(QWidget *parent) : QMainWindow(parent), ui(new U

19、i:MainWindow),sharememory2(share2) char str128,f_id128; ui-setupUi(this); setWindowTitle(put); setWindowFlags(Qt:Dialog); move(1000,0); resize(500,500); sprintf(str,%d,getpid(); sprintf(f_id,%d,getppid(); ui-textBrowser-setText(put); ui-textBrowser_2-setText(str); ui-textBrowser_3-setText(f_id); QTi

20、mer *timer = new QTimer(this); connect(timer, SIGNAL(timeout(), this, SLOT(timerUpDate(); timer-start(1);MainWindow:MainWindow() delete ui;void MainWindow:timerUpDate() QDateTime time = QDateTime:currentDateTime(); QString str = time.toString(yyyy-MM-dd hh:mm:ss dddd); ui-labelCurDate-setText(str);4

21、.2實(shí)驗(yàn)二4.2.1 實(shí)驗(yàn)要求掌握系統(tǒng)調(diào)用的實(shí)現(xiàn)過程,通過編譯內(nèi)核方法,增加一個(gè)新的系統(tǒng)調(diào)用,另編寫一個(gè)應(yīng)用程序,調(diào)用新增加的系統(tǒng)調(diào)用。4.2.2 具體實(shí)現(xiàn)(1) 系統(tǒng)調(diào)用的原理用戶進(jìn)程不能訪問內(nèi)核所占內(nèi)存空間,也不能調(diào)用內(nèi)核函數(shù)。進(jìn)程調(diào)用一個(gè)特殊的指令,這個(gè)指令會(huì)跳到一個(gè)事先定義的內(nèi)核中的一個(gè)位置。在 Intel CPU 中,由中斷 INT 0 x80 實(shí)現(xiàn)。 (與 DOS 功能調(diào)用 int0 x21 很相似)跳轉(zhuǎn)到的內(nèi)核位置叫做sysem_call。檢查系統(tǒng)調(diào)用號(hào),這個(gè)號(hào)碼代表進(jìn)程請(qǐng)求哪種服務(wù)。然后,它查看系統(tǒng)11華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告調(diào)用表

22、(sys_call_table)找到所調(diào)用的內(nèi)核函數(shù)入口地址。接著,就調(diào)用函數(shù),等返回后,做一些系統(tǒng)檢查,最后返回到進(jìn)程(如果這個(gè)進(jìn)程時(shí)間用盡,就返回到其他進(jìn)程) 。(2) 編寫新的系統(tǒng)調(diào)用程序新的系統(tǒng)調(diào)用程序?qū)崿F(xiàn)的功能是:將一個(gè)文件中的內(nèi)容拷貝到另一個(gè)文件中。這個(gè)系統(tǒng)調(diào)用的參數(shù)是兩個(gè) char*型的字符指針 SourceFile、GoalFile,分別表示源文件和目標(biāo)文件的路徑名。用戶進(jìn)程中的 open、read、write、close 函數(shù)此時(shí)對(duì)應(yīng)內(nèi)核函數(shù) sys_open、 sys_read、 sys_write、 sys_close 函數(shù)。循環(huán)拷貝的判斷條件還是 sys_read的返回

23、值,當(dāng)其大于 0 的時(shí)候執(zhí)行循環(huán),否則表示源文件已拷貝到了目標(biāo)文件。 mm_segment_t 類型的變量 fs 的作用是在讀寫文件前得到當(dāng)前 fs,避免使用的緩沖區(qū)超過了用戶空間的地址范圍而報(bào)錯(cuò)。詳細(xì)代碼見 4.2.3。(3) 編譯內(nèi)核下載并解壓內(nèi)核先到 Linux 官方網(wǎng)站 /下載內(nèi)核 linux-3.14.36.tar.xz。打開終端,使用 sudo su 獲取 root 權(quán)限,然后使用 cp linux-3.14.36.tar.xz /usr/src 命令將linux-3.14.36.tar.xz 復(fù)制到文件夾/usr/src 下,復(fù)制完畢之后將

24、其解壓,用到的命令為:xz -d linux-3.14.36.tar.xz 和 tar xvf linux-3.14.36.tar。修改內(nèi)核新的內(nèi)核解壓完畢后,使用 cd /usr/src/linux-3.14.36 命令進(jìn)入目錄 /usr/src/linux-3.14.36。然后使用命令 sudo gedit kernel/sys.c 打開 sys.c,將新的系統(tǒng)調(diào)用程序復(fù)制到該文件的文件末尾,保存退出,系統(tǒng)調(diào)用程序詳細(xì)代碼見 4.2.3。使用命令 sudo gedit arch/x86/syscalls/syscall_64.tbl 打開 syscall_64.tbl 添加系統(tǒng)調(diào)用號(hào)。在該

25、文件中添加一行內(nèi)容 317 common mycall sys_mycall,其中系統(tǒng)調(diào)用號(hào)317 不是固定的,只要該文件中沒有出現(xiàn)的數(shù)字都可以使用。添加之后保存退出。使用命令 sudo gedit include/asm-generic/syscalls.h 打開 syscalls.h,在“#endif /* _ASM_GENERIC_SYSCALLS_H */ 這一行的上面一行添加新的系統(tǒng)調(diào)用程序的函數(shù)定義,即:#ifndef sys_mycall12華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告asmlinkage int sys_mycall(char* sou

26、rceFile,char* destFile);#endif然后保存退出。編譯內(nèi)核在編譯內(nèi)核之前先要安裝 ncurses 庫,使用命令 sudo apt-get install libncurses5-dev安裝。安裝完畢后,進(jìn)入 /usr/src/linux-3.14.36 目錄下,新建一個(gè)腳本文件mysyscall.sh,通過命令 gedit mysyscall.sh 打開該腳本文件進(jìn)行編輯。將以下內(nèi)容添加到腳本中:#!/bin/bashmake mrproper make menuconfig make depmake clean make bzImage j4make modules

27、j4make modules_install j4make install j4mkinitramfs -o /boot/initrd.img-3.14.34 update-grub reboot保存退出,然后修改腳本文件的權(quán)限,使其可以對(duì)內(nèi)核文件進(jìn)行操作,修改權(quán)限的命令為 chmod 777 mysyscall.sh。權(quán)限修改成功后,在終端中運(yùn)行該腳本文件./mysyscall.sh,內(nèi)核開始編譯,期間會(huì)出現(xiàn)配置 linux 過程,直接先 save,然后 OK,再 exit 即可,繼續(xù)等待編譯結(jié)束。編譯完成后,電腦會(huì)自動(dòng)重啟,重啟選擇進(jìn)入U(xiǎn)buntu 高級(jí)選項(xiàng),在選項(xiàng)列表中選擇新內(nèi)核 lin

28、ux-3.14.36 進(jìn)入,打開終端輸入uname -a 查看系統(tǒng)版本號(hào),執(zhí)行情況如下所示:說明已經(jīng)成功進(jìn)入新的內(nèi)核 linux-3.14.36 中。(4) 編寫系統(tǒng)調(diào)用測(cè)試程序需要用到的頭文件是 syscall.h、unistd.h、stdlib.h。在 main 函數(shù)中直接調(diào)用頭文13華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告件 syscall.h 中定義的函數(shù) syscall,該函數(shù)有三個(gè)參數(shù),第一個(gè)參數(shù)是系統(tǒng)調(diào)用號(hào)(317) ,第二個(gè)參數(shù)是源文件(main.c,即測(cè)試程序的源代碼文件) ,第三個(gè)參數(shù)是目標(biāo)文件(yyk.text) 。程序運(yùn)行結(jié)果為:在 mai

29、n.c 所在目錄下新建了一個(gè) yyk.text 文件,并將 main.c中的代碼拷貝到了 yyk.text 中。詳細(xì)代碼見 4.2.3。4.2.3 源代碼(1) 系統(tǒng)調(diào)用程序asmlinkage int sys_mycall(char* SourceFile,char* GoalFile) int source=sys_open(SourceFile,O_RDONLY,0); int goal=sys_open(GoalFile,O_WRONLY|O_CREAT|O_TRUNC,0600); char buff4096; mm_segment_t fs; fs = get_fs(); set_

30、fs(get_ds(); int i; if(source0 & goal0) do i=sys_read(source,buff,4096); sys_write(goal,buff,i); while(i); else printk(Error!); sys_close(source); sys_close(goal); set_fs(fs); return 10;(2) 測(cè)試程序#include #include #include int main() syscall(317,main.c,yyk.text); return 0;14華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程

31、 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告4.3實(shí)驗(yàn)三4.3.1 實(shí)驗(yàn)要求掌握增加設(shè)備驅(qū)動(dòng)程序的方法。通過模塊方法,增加一個(gè)新的設(shè)備驅(qū)動(dòng)程序,其功能可以簡(jiǎn)單。 (實(shí)現(xiàn)字符設(shè)備的驅(qū)動(dòng))4.3.2 具體實(shí)現(xiàn)(1)Linux 核心是一種 monolithic 類型的內(nèi)核,即單一的大核心,另外一種形式是MicroKernel,核心的所有功能部件都被拆成獨(dú)立部分, 這些部分之間通過嚴(yán)格的通訊機(jī)制進(jìn)行聯(lián)系。Linux 內(nèi)核是一個(gè)整體結(jié)構(gòu),因此向內(nèi)核添加任何東西.或者刪除某些功能,都十分困難 。為了解決這個(gè)問題,引入了模塊機(jī)制,從而可以動(dòng)態(tài)的在內(nèi)核中添加或者刪除模塊。模塊一旦被插入內(nèi)核,就和內(nèi)核其他部分一樣。Linux 內(nèi)核

32、中的設(shè)備驅(qū)動(dòng)程序是一組常駐內(nèi)存的具有特權(quán)的共享庫,是低級(jí)硬件處理例程。對(duì)用戶程序而言,設(shè)備驅(qū)動(dòng)程序隱藏了設(shè)備的具體細(xì)節(jié), 對(duì)各種不同設(shè)備提供了一致的接口,一般來說是把設(shè)備映射為一個(gè)特殊的設(shè)備文 件,用戶程序可以像對(duì)其它文件一樣對(duì)此設(shè)備文件進(jìn)行操作。Linux 支持 3 種設(shè)備:字符設(shè)備、塊設(shè)備和網(wǎng)絡(luò)設(shè)備。設(shè)備由一個(gè)主設(shè)備號(hào)和一個(gè)次設(shè)備號(hào)標(biāo)識(shí)。主設(shè)備號(hào)唯一標(biāo)識(shí)了設(shè)備類型, 即設(shè)備驅(qū)動(dòng)程序類型,它是塊設(shè)備表或字符設(shè)備表中設(shè)備表項(xiàng)的索引。次設(shè)備號(hào)僅由設(shè)備驅(qū)動(dòng)程序解釋 ,一般用于識(shí)別在若干可能的硬件設(shè)備中,I/O 請(qǐng)求所涉及到的那個(gè)設(shè)備。典型的 Linux 模塊實(shí)現(xiàn)機(jī)制有如下幾步:注冊(cè)設(shè)備:在系統(tǒng)初啟

33、或者加載模塊的時(shí)候,必須將設(shè)備登記到相應(yīng)的設(shè)備數(shù)組,并返回主設(shè)備號(hào)。定義功能函數(shù):對(duì)于每一個(gè)驅(qū)動(dòng)函數(shù)來說,都有一些和此設(shè)備密切相關(guān)的功能函數(shù)。以最常用的塊設(shè)備或者字符設(shè)備來說,都存在著諸如 open()、read()這一類的操作。當(dāng)系統(tǒng)調(diào)用這些調(diào)用時(shí),將自動(dòng)的使用驅(qū)動(dòng)函數(shù)中特定的模塊來實(shí)現(xiàn)具體的操作。卸載設(shè)備:在不用這個(gè)設(shè)備時(shí),可以將它卸載,主要是從/proc 中取消這個(gè)設(shè)備的特殊文件。15華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告(2) 編寫 Makefile 文件Makefile 文件用于編譯設(shè)備驅(qū)動(dòng)程序,其內(nèi)容如下:ifneq ($(KERNELRELEASE

34、),) #kbuild syntax.#模塊的文件組成mymodule-objs :=MyDeviceDriver.o #生成的模塊文件名 obj-m := MyDeviceDriver.o elsePWD :=$(shell pwd)KVER :=$(shell uname -r)KDIR :=/lib/modules/$(KVER)/buildall:$(MAKE) -C $(KDIR) M=$(PWD)clean:#rm -f *.cmd *.o *.mod *.korm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions#$(MAKE) -C $(KDI

35、R) M=$(PWD) cleanendif(3)編寫設(shè)備功能函數(shù)編寫設(shè)備驅(qū)動(dòng)程序的主要工作就是編寫子功能函數(shù),并填充 file_operations 的各個(gè)域 。結(jié)構(gòu)體 file_operations 的具體定義如下:struct file_operations struct module *owner;/擁有該結(jié)構(gòu)的模塊的指針,一般為 THIS_MODULES loff_t (*llseek) (struct file *, loff_t, int);/用來修改文件當(dāng)前的讀寫位置 ssize_t (*read) (struct file *, char _user *, size_t, l

36、off_t *);/從設(shè)備中同步讀取數(shù)據(jù) ssize_t (*write) (struct file *, const char _user *, size_t, loff_t *);/向設(shè)備發(fā)送數(shù)據(jù)ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);/初始化一個(gè)異步的讀取操作 ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);/初始化一個(gè)異步的寫入操作 int (*r

37、eaddir) (struct file *, void *, filldir_t);/僅用于讀取目錄,對(duì)于設(shè)備文件,該字段為NULL unsigned int (*poll) (struct file *, struct poll_table_struct *); /輪詢函數(shù),判斷目前是否可以進(jìn)行非阻塞的讀寫或?qū)懭?int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); /執(zhí)行設(shè)備 I/O 控制命令 long (*unlocked_ioctl) (struct file *, unsigned in

38、t, unsigned long); /不使用 BLK 文件系統(tǒng),將使用此種函數(shù)指針代替 ioctl long (*compat_ioctl) (struct file *, unsigned int, unsigned long); /在 64 位系統(tǒng)上,32 位的ioctl 調(diào)用將使用此函數(shù)指針代替 int (*mmap) (struct file *, struct vm_area_struct *); /用于請(qǐng)求將設(shè)備內(nèi)存映射到進(jìn)程地址空間 int (*open) (struct inode *, struct file *); /打開 int (*flush) (struct fil

39、e *, fl_owner_t id); int (*release) (struct inode *, struct file *); /關(guān)閉 int (*fsync) (struct file *, struct dentry *, int datasync); /刷新待處理的數(shù)據(jù) int (*aio_fsync) (struct kiocb *, int datasync); /異步刷新待處理的數(shù)據(jù) 16華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告 int (*fasync) (int, struct file *, int); /通知設(shè)備 FASYNC 標(biāo)志發(fā)

40、生變化 int (*lock) (struct file *, int, struct file_lock *); ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); int (*check_flags)(int); int (*flock) (struct file

41、*, int, struct file_lock *); ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); int (*setlease)(struct file *, long, struct file_lock *); ;子功能函數(shù)詳細(xì)代碼見 4.4.3。

42、(4) 設(shè)備驅(qū)動(dòng)程序安裝 make clean,清除 make 產(chǎn)生的殘留 make,重新調(diào)用 Makefile 編譯設(shè)備驅(qū)動(dòng)程序 insmod -f MyDeviceDriver.ko,加載生成的 MyDeviceDriver.ko 模塊 cat /proc/devices,獲取設(shè)備驅(qū)動(dòng)程序的主設(shè)備號(hào)mknod /dev/MyDeviceDriver c 250 0,創(chuàng)建設(shè)備文件,250 為主設(shè)備號(hào),0 為從設(shè)備號(hào)(5)測(cè)試驅(qū)動(dòng)程序此設(shè)備驅(qū)動(dòng)程序?qū)崿F(xiàn)的功能是將一個(gè)字符串中內(nèi)容拷貝到另外一個(gè)字符串中。測(cè)試程序編寫完成后,在終端輸入 gcc test.c -o test 進(jìn)行編譯。測(cè)試結(jié)果如下:

43、詳細(xì)代碼見 4.3.3。4.3.3 源代碼(1) 設(shè)備驅(qū)動(dòng)程序#include 17華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告#include #include #include #include #include #include #include #define DEV_SIZE 102400 /設(shè)備申請(qǐng)的最大內(nèi)存空間struct Device char *data;/數(shù)組指針,用于存放從用戶讀入的數(shù)據(jù) long size;/存儲(chǔ)的數(shù)據(jù)長度*devp;struct cdev cdev;/字符設(shè)備結(jié)構(gòu)體static int devNum_major = 0;/主設(shè)

44、備號(hào)變量/對(duì)應(yīng)用戶態(tài)的 lseekstatic loff_t my_llseek(struct file *file,loff_t offset, int whence) loff_t cfo=0;/文件當(dāng)前偏移量,current file offset switch(whence) case 0:/SEEK_SET cfo=offset;break;case 1:/SEEK_CUR cfo=file-f_pos+offset;break;case 2:/SEEK_END cfo=DEV_SIZE-1+offset;break; if (cfoDEV_SIZE)/文件偏移量越界 return

45、-EINVAL; file-f_pos = cfo; return cfo;/對(duì)應(yīng)用戶態(tài)的 read,寫數(shù)據(jù)到用戶空間static ssize_t my_read(struct file *file, char _user *buf, size_t count, loff_t *p_cfo) int val = 0; struct Device *dev = file-private_data; /設(shè)備描述結(jié)構(gòu)體指針,獲取設(shè)備信息 if (copy_to_user(buf, (void*)(dev-data + *p_cfo), count)/如果成功返回 0;如果失敗,返回未完成 copy

46、的長度18華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告 val = -EFAULT; else *p_cfo += count;/copy 成功,文件偏移量加上 count val = count; return val;/對(duì)應(yīng)用戶態(tài)的 write,從用戶空間讀入數(shù)據(jù)static ssize_t my_write(struct file *file, const char _user *buf, size_t count, loff_t *p_cfo) int val = 0; struct Device *dev = file-private_data; if (c

47、opy_from_user(dev-data + *p_cfo, buf, count)/如果成功返回 0;如果失敗,返回未完成 copy 的長度 val = -EFAULT; else *p_cfo += count;/copy 成功,文件偏移量加上 count val = count; return val;static int my_open(struct inode *inode, struct file *file) file-private_data = devp; return 0;struct file_operations fops= .owner = THIS_MODULE

48、, .llseek = my_llseek, .read = my_read, .write = my_write, .open = my_open,;int init_module(void)int dev_num;dev_num = register_chrdev(0,MyDeviceDriver,&fops);if (dev_num 0) 19華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告printk(KERN_INFO MyDeviceDriver: FAIL to get major numbern);return dev_num;if (devNum

49、_major = 0) devNum_major = dev_num; /初始化 cdev 結(jié)構(gòu) cdev_init(&cdev, &fops); cdev.owner = THIS_MODULE; cdev.ops = &fops; cdev_add(&cdev,MKDEV(devNum_major, 0), 1);/注冊(cè) 1 個(gè)字符設(shè)備 /為設(shè)備描述結(jié)構(gòu)體分配內(nèi)存 devp = kmalloc(sizeof(struct Device), GFP_KERNEL); if (!devp) dev_num = -ENOMEM; printk(KERN_INFO

50、MyDeviceDriver: FAIL to get memoryn); return dev_num; (*devp).size = DEV_SIZE; (*devp).data = kmalloc(DEV_SIZE, GFP_KERNEL); memset(*devp).data, 0, (*devp).size);/初始化為 0 return 0;void cleanup_module(void)cdev_del(&cdev);/注銷設(shè)備 kfree(devp);/注銷設(shè)備結(jié)構(gòu)體 kfree(*devp).data);/注銷設(shè)備內(nèi)存空間 unregister_chrdev(de

51、vNum_major,MyDeviceDriver);/卸載主設(shè)備號(hào)MODULE_LICENSE(GPL);(2) 驅(qū)動(dòng)程序測(cè)試程序#include #include #include #define BUFFER_SIZE 102400int main(void)int dev,i=0;char c; char sourceBUFFER_SIZE;/寫入 MyDeviceDriver 設(shè)備的內(nèi)容 char goalBUFFER_SIZE; /MyDeviceDriver 設(shè)備的內(nèi)容讀入到該 goal 中printf(input the string you want to write in

52、your device:n);while(c=getchar()!=n)20華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告sourcei+=c;printf(n); if(dev=open(/dev/MyDeviceDriver,O_RDWR)=-1) /打開 MyDeviceDriver 設(shè)備失敗 printf(FAIL to open MyDeviceDriver!n);else/成功 printf(SUCCESS to open MyDeviceDriver!n); printf(source:n%snn,source); write(dev,source,siz

53、eof(source); /把 source 中的內(nèi)容寫入 MyDeviceDriver 設(shè)備 lseek(dev,0,SEEK_SET); /把文件指針定位到文件開始的位置 read(dev,goal,sizeof(source); /把 MyDeviceDriver 設(shè)備中的內(nèi)容讀入到 goal 中 printf(goal:n%snn,goal); return 0;4.4實(shí)驗(yàn)四實(shí)驗(yàn)四有兩個(gè)選做題目,分別是 proc 文件監(jiān)控系統(tǒng)和小型文件系統(tǒng),本次實(shí)驗(yàn)我選擇的題目是 proc 文件監(jiān)控系統(tǒng)。4.4.1 實(shí)驗(yàn)要求了解/proc 文件的特點(diǎn)和使用方法;監(jiān)控系統(tǒng)狀態(tài),顯示系統(tǒng)中若干部件使用狀態(tài)

54、;用圖形界面實(shí)現(xiàn)系統(tǒng)監(jiān)控狀態(tài)。4.4.2 具體實(shí)現(xiàn)(1)/proc 文件系統(tǒng)的特點(diǎn)Linux 的 PROC 文件系統(tǒng)是進(jìn)程文件系統(tǒng)和內(nèi)核文件系統(tǒng)的組成的復(fù)合體,是將內(nèi)核數(shù)據(jù)對(duì)象化為文件形式進(jìn)行存取的一種內(nèi)存文件系統(tǒng),是監(jiān)控內(nèi)核的一種用戶接口。它擁有一些特殊的文件(純文本) ,從中可以獲取系統(tǒng)狀態(tài)信息。(2)功能清單獲取并顯示主機(jī)名,與之相關(guān)的 proc 文件為/proc/sys/kernel/hostname;獲取并顯示系統(tǒng)啟動(dòng)的時(shí)間,與之相關(guān)的 proc 文件為/proc/uptime;顯示系統(tǒng)到目前為止持續(xù)運(yùn)行的時(shí)間,與之相關(guān)的 proc 文件為/proc/uptime;顯示系統(tǒng)的版本號(hào),

55、與之相關(guān)的 proc 文件為/proc/sys/kernel/ostype 和/proc/sys/kernel/osrelease; 顯示 CPU 的型號(hào)和主頻大小,與之相關(guān)的 proc 文件為/proc/cpuinfo;21華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告通過 pid 或者進(jìn)程名查詢一個(gè)進(jìn)程,并顯示該進(jìn)程的詳細(xì)信息,提供殺掉該進(jìn)程的功能,與之相關(guān)的 proc 文件為/proc/(pid)/stat;顯示系統(tǒng)所有進(jìn)程的一些信息,包括 pid、ppid、占用內(nèi)存大小、優(yōu)先級(jí)等,與之相關(guān)的 proc 文件為/proc/(pid)/stat, /proc/(pi

56、d)/statm;CPU 使用率的圖形化顯示(2 分鐘內(nèi)的歷史記錄曲線) ,與之相關(guān)的 proc 文件為/proc/stat;內(nèi)存和交換分區(qū)的使用率的圖形化顯示(2 分鐘內(nèi)的歷史曲線) ,與之有關(guān)的proc 文件為/proc/meminfo;在狀態(tài)欄顯示當(dāng)前時(shí)間,未使用到/proc 中的文件;在狀態(tài)欄顯示當(dāng)前 CPU 使用率,與之相關(guān)的 proc 文件為/proc/stat;在狀態(tài)欄顯示當(dāng)前內(nèi)存使用情況,與之相關(guān)的 proc 文件為/proc/meminfo;用新線程運(yùn)行一個(gè)其他程序,未使用到/proc 中的文件;關(guān)機(jī)功能,未使用到/proc 中的文件;(3)功能實(shí)現(xiàn)獲取并顯示主機(jī)名用 fop

57、en 函數(shù)打開/proc/sys/kernel/hostname 文件,然后以文件指針為輸入流,用fgets 從其中讀出一行字符包含主機(jī)名,然后用格式化輸出函數(shù) sscanf 函數(shù)輸出一個(gè)字符串,即主機(jī)名。獲取并顯示系統(tǒng)啟動(dòng)的時(shí)間從文件/proc/uptime 中獲取系統(tǒng)啟動(dòng)到現(xiàn)在的運(yùn)行時(shí)間(單位是 s) ,然后調(diào)用time 函數(shù)獲取系統(tǒng)當(dāng)前時(shí)間(單位是 s) ,用當(dāng)前時(shí)間秒數(shù)減去運(yùn)行時(shí)間秒數(shù)即為系統(tǒng)啟動(dòng)的時(shí)間秒數(shù),然后調(diào)用 localtime 函數(shù)將系統(tǒng)啟動(dòng)時(shí)間秒數(shù)轉(zhuǎn)換成 tm 結(jié)構(gòu)體類型的變量,該變量中的成員包括年份、月份、日期、星期幾、時(shí)、分、秒等,再調(diào)用輸出函數(shù)輸出即可。顯示系統(tǒng)到目前

58、為止持續(xù)運(yùn)行的時(shí)間用 fopen 函數(shù)打開/proc/uptime 文件,然后以文件指針為輸入流,用 fgets 從其中讀出一行字符包含系統(tǒng)運(yùn)行時(shí)間,然后用格式化輸入函數(shù) sscanf 從讀取出的字符流中輸入一個(gè) float 類型的數(shù)到 runtime,即系統(tǒng)運(yùn)行的時(shí)間。顯示系統(tǒng)的版本號(hào)22華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計(jì)計(jì) 報(bào)報(bào) 告告從/proc/sys/kernel/ostype 和/proc/sys/kernel/osrelease 中讀取系統(tǒng)類型(比如linux)和系統(tǒng)內(nèi)核版本號(hào),處理方法和獲取系統(tǒng)運(yùn)行時(shí)間的方法一樣。得到系統(tǒng)類型和系統(tǒng)內(nèi)核版本號(hào)之后,調(diào)用 QS

59、tring 類的方法 arg 將兩個(gè)字符串連接起來,再輸出顯示即可。顯示 CPU 的型號(hào)和主頻大小打開/proc/cpuinfo 文件后發(fā)現(xiàn) CPU 有四個(gè),相同的型號(hào),不同的主頻,后來才弄清楚所謂的四個(gè) CPU 是 CPU 的四個(gè)核心,而“主頻”并不是主頻,而是當(dāng)前時(shí)刻該核心所使用的 CPU 核心頻率,隨時(shí)間而變化的。弄清楚文件中的內(nèi)容的含義之后,開始處理/proc/cpuinfo,從中讀取 CPU 的型號(hào)和頻率。處理這個(gè)文件沒有用到 fopen 等函數(shù),而是使用了 Qt 自帶的兩個(gè)類 QFile和 QTextStream,定義一個(gè) QFile 類型的變量 file,并用路徑名“/proc/

60、cpuinfo”初始化該變量,其作用是以只讀方式打開文件/proc/cpuinfo,然后以 file 的地址作為參數(shù)初始化 QTextStream 類型的變量 stream,其作用是將/proc/cpuinfo 文件中的內(nèi)容以字符流的形式存入變量 stream 中,相當(dāng)于一個(gè)文本流。由于 CPU 的型號(hào)是一樣的,所以只讀取第一個(gè)型號(hào)名稱即可,根據(jù) CPU 型號(hào)名稱所在的行,采用 while 循環(huán)讀取stream 中的內(nèi)容,每次讀取一行,當(dāng)行數(shù)等于 CPU 型號(hào)所在行時(shí),將讀取出的一行賦值給一個(gè) QString 類型的變量,再調(diào)用 QString 的方法 mid 截取 CPU 型號(hào)名稱,file.close()關(guān)閉 file。CPU 四個(gè)核心的主

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論