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

下載本文檔

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

文檔簡介

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

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

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

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

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

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

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

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

9、tf 把進程號轉(zhuǎn)換成字符串類型之后寫在標簽上并添加至窗口即可。主進程和三個子進程的程序全部編寫完后,直接在 Qt 上編譯運行。程序運行結(jié)果如下所示:6華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計計 報報 告告詳細代碼見 4.1.3。7華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計計 報報 告告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) 三個并發(fā)進程#主進程主進程 MAIN#include #include #include #include #include #include int main(int argc, char *argv)8華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計計 報報 告告 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();#子進程子進程 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è) 計計 報報 告告 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);#子進程子進程 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);#子進程子進程 putmainwindow.cpp#include mainwindow.h#include ui_mainwindow.h10華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計計 報報 告告#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實驗二4.2.1 實驗要求掌握系統(tǒng)調(diào)用的實現(xiàn)過程,通過編譯內(nèi)核方法,增加一個新的系統(tǒng)調(diào)用,另編寫一個應(yīng)用程序,調(diào)用新增加的系統(tǒng)調(diào)用。4.2.2 具體實現(xiàn)(1) 系統(tǒng)調(diào)用的原理用戶進程不能訪問內(nèi)核所占內(nèi)存空間,也不能調(diào)用內(nèi)核函數(shù)。進程調(diào)用一個特殊的指令,這個指令會跳到一個事先定義的內(nèi)核中的一個位置。在 Intel CPU 中,由中斷 INT 0 x80 實現(xiàn)。 (與 DOS 功能調(diào)用 int0 x21 很相似)跳轉(zhuǎn)到的內(nèi)核位置叫做sysem_call。檢查系統(tǒng)調(diào)用號,這個號碼代表進程請求哪種服務(wù)。然后,它查看系統(tǒng)11華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計計 報報 告告調(diào)用表

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

23、值,當其大于 0 的時候執(zhí)行循環(huán),否則表示源文件已拷貝到了目標文件。 mm_segment_t 類型的變量 fs 的作用是在讀寫文件前得到當前 fs,避免使用的緩沖區(qū)超過了用戶空間的地址范圍而報錯。詳細代碼見 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 命令進入目錄 /usr/src/linux-3.14.36。然后使用命令 sudo gedit kernel/sys.c 打開 sys.c,將新的系統(tǒng)調(diào)用程序復(fù)制到該文件的文件末尾,保存退出,系統(tǒng)調(diào)用程序詳細代碼見 4.2.3。使用命令 sudo gedit arch/x86/syscalls/syscall_64.tbl 打開 syscall_64.tbl 添加系統(tǒng)調(diào)用號。在該

25、文件中添加一行內(nèi)容 317 common mycall sys_mycall,其中系統(tǒng)調(dià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è) 計計 報報 告告asmlinkage int sys_mycall(char* sou

26、rceFile,char* destFile);#endif然后保存退出。編譯內(nèi)核在編譯內(nèi)核之前先要安裝 ncurses 庫,使用命令 sudo apt-get install libncurses5-dev安裝。安裝完畢后,進入 /usr/src/linux-3.14.36 目錄下,新建一個腳本文件mysyscall.sh,通過命令 gedit mysyscall.sh 打開該腳本文件進行編輯。將以下內(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)限,使其可以對內(nèi)核文件進行操作,修改權(quán)限的命令為 chmod 777 mysyscall.sh。權(quán)限修改成功后,在終端中運行該腳本文件./mysyscall.sh,內(nèi)核開始編譯,期間會出現(xiàn)配置 linux 過程,直接先 save,然后 OK,再 exit 即可,繼續(xù)等待編譯結(jié)束。編譯完成后,電腦會自動重啟,重啟選擇進入Ubuntu 高級選項,在選項列表中選擇新內(nèi)核 lin

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

29、n.c 所在目錄下新建了一個 yyk.text 文件,并將 main.c中的代碼拷貝到了 yyk.text 中。詳細代碼見 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) 測試程序#include #include #include int main() syscall(317,main.c,yyk.text); return 0;14華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程

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

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

33、或者加載模塊的時候,必須將設(shè)備登記到相應(yīng)的設(shè)備數(shù)組,并返回主設(shè)備號。定義功能函數(shù):對于每一個驅(qū)動函數(shù)來說,都有一些和此設(shè)備密切相關(guān)的功能函數(shù)。以最常用的塊設(shè)備或者字符設(shè)備來說,都存在著諸如 open()、read()這一類的操作。當系統(tǒng)調(diào)用這些調(diào)用時,將自動的使用驅(qū)動函數(shù)中特定的模塊來實現(xiàn)具體的操作。卸載設(shè)備:在不用這個設(shè)備時,可以將它卸載,主要是從/proc 中取消這個設(shè)備的特殊文件。15華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計計 報報 告告(2) 編寫 Makefile 文件Makefile 文件用于編譯設(shè)備驅(qū)動程序,其內(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ū)動程序的主要工作就是編寫子功能函數(shù),并填充 file_operations 的各個域 。結(jié)構(gòu)體 file_operations 的具體定義如下:struct file_operations struct module *owner;/擁有該結(jié)構(gòu)的模塊的指針,一般為 THIS_MODULES loff_t (*llseek) (struct file *, loff_t, int);/用來修改文件當前的讀寫位置 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);/初始化一個異步的讀取操作 ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);/初始化一個異步的寫入操作 int (*r

37、eaddir) (struct file *, void *, filldir_t);/僅用于讀取目錄,對于設(shè)備文件,該字段為NULL unsigned int (*poll) (struct file *, struct poll_table_struct *); /輪詢函數(shù),判斷目前是否可以進行非阻塞的讀寫或?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 *); /用于請求將設(shè)備內(nèi)存映射到進程地址空間 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è) 計計 報報 告告 int (*fasync) (int, struct file *, int); /通知設(shè)備 FASYNC 標志發(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ù)詳細代碼見 4.4.3。

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

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

44、備號變量/對應(yīng)用戶態(tài)的 lseekstatic loff_t my_llseek(struct file *file,loff_t offset, int whence) loff_t cfo=0;/文件當前偏移量,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;/對應(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è) 計計 報報 告告 val = -EFAULT; else *p_cfo += count;/copy 成功,文件偏移量加上 count val = count; return val;/對應(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è) 計計 報報 告告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);/注冊 1 個字符設(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è)備號MODULE_LICENSE(GPL);(2) 驅(qū)動程序測試程序#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è) 計計 報報 告告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實驗四實驗四有兩個選做題目,分別是 proc 文件監(jiān)控系統(tǒng)和小型文件系統(tǒng),本次實驗我選擇的題目是 proc 文件監(jiān)控系統(tǒng)。4.4.1 實驗要求了解/proc 文件的特點和使用方法;監(jiān)控系統(tǒng)狀態(tài),顯示系統(tǒng)中若干部件使用狀態(tài)

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

55、與之相關(guān)的 proc 文件為/proc/sys/kernel/ostype 和/proc/sys/kernel/osrelease; 顯示 CPU 的型號和主頻大小,與之相關(guān)的 proc 文件為/proc/cpuinfo;21華華 中中 科科 技技 大大 學(xué)學(xué) 課課 程程 設(shè)設(shè) 計計 報報 告告通過 pid 或者進程名查詢一個進程,并顯示該進程的詳細信息,提供殺掉該進程的功能,與之相關(guān)的 proc 文件為/proc/(pid)/stat;顯示系統(tǒng)所有進程的一些信息,包括 pid、ppid、占用內(nèi)存大小、優(yōu)先級等,與之相關(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)欄顯示當前時間,未使用到/proc 中的文件;在狀態(tài)欄顯示當前 CPU 使用率,與之相關(guān)的 proc 文件為/proc/stat;在狀態(tài)欄顯示當前內(nèi)存使用情況,與之相關(guān)的 proc 文件為/proc/meminfo;用新線程運行一個其他程序,未使用到/proc 中的文件;關(guān)機功能,未使用到/proc 中的文件;(3)功能實現(xiàn)獲取并顯示主機名用 fop

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

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

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

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

溫馨提示

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

最新文檔

評論

0/150

提交評論