版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
課程設計報告題目:操作系統(tǒng)課程設計課程名稱:操作系統(tǒng)專業(yè)班級:信息安全1302學號: 姓名:指導教師:報告日期:2016年3月17日計算機科學與技術學院目錄TOC\o"1-3"1 文件拷貝、多窗口進程并發(fā) 31.1 課設內(nèi)容 31.2 課設要求 31.3 具體實現(xiàn) 31.3.1 文件拷貝 31.3.2 多窗口進程并發(fā) 51.4 測試結(jié)果 51.4.1 文件拷貝 51.4.2 多窗口進程并發(fā) 71.5 源代碼 72 增加系統(tǒng)調(diào)用、編譯內(nèi)核 102.1 課設內(nèi)容 102.2 課設要求 102.3 實驗環(huán)境 102.4 具體實現(xiàn) 102.4.1 系統(tǒng)調(diào)用的原理 102.4.2 編寫新的系統(tǒng)調(diào)用程序 102.4.3 編譯內(nèi)核 112.5 測試結(jié)果 132.6 源代碼 143 增加字符設備驅(qū)動程序 153.1 課設內(nèi)容 153.2 課設要求 153.3 具體實現(xiàn) 153.3.1 模塊機制 153.3.2 Makefile 163.3.3 安裝設備驅(qū)動 163.4 測試結(jié)果 164 系統(tǒng)監(jiān)控器 184.1 課設內(nèi)容 184.2 UI設計 184.3 主要功能實現(xiàn) 204.3.1 獲取并顯示主機名 204.3.2 顯示系統(tǒng)當前時間、持續(xù)時間和啟動時間 214.3.3 顯示系統(tǒng)的版本號 234.3.4 顯示cpu的型號和主頻大小 254.3.5 顯示所有進程的信息 274.3.6 通過pid或進程名查詢或殺死進程 324.3.7 顯示當前內(nèi)存和交換分區(qū)使用情況 424.3.8 顯示當前CPU使用率 464.3.9 cpu和內(nèi)存使用率的圖形化顯示 494.3.10 關機和重啟 514.3.11 作者信息 514.4 全局效果 525 課設感悟 55文件拷貝、多窗口進程并發(fā)課設內(nèi)容掌握Linux操作系統(tǒng)的使用方法,包括鍵盤命令、系統(tǒng)調(diào)用;掌握在Linux下的編程環(huán)境。課設要求編寫一個C程序,其內(nèi)容為實現(xiàn)文件拷貝的功能。編寫一個C程序,其內(nèi)容為分窗口同時顯示三個并發(fā)進程的運行結(jié)果。要求用到Linux下的圖形庫(GTK/Qt)。具體實現(xiàn)文件拷貝在windows操作系統(tǒng)上實現(xiàn)的文件拷貝功能一般使用fopen、fread、fwrite三個來自標準C函數(shù)庫的函數(shù)執(zhí)行對文件的打開、讀、寫操作,而本次實驗要求使用Linux系統(tǒng)的系統(tǒng)調(diào)用open、read、write實現(xiàn)上述三個操作。具體設計思路如下:打開兩個文件(分別是源文件和目標文件,可以是任意字符流形式存儲的文件,包括文本文件、照片等),調(diào)用read函數(shù)讀取源文件的內(nèi)容,將read的返回值作為while循環(huán)的判斷條件,當返回值大于0(即還未讀取完畢源文件中的內(nèi)容)時,調(diào)用write執(zhí)行向目標文件寫的操作,否則跳出循環(huán),表示源文件已經(jīng)被拷貝到目標文件,然后調(diào)用close關閉源文件和目標文件。涉及到的主要系統(tǒng)調(diào)用如下:open()函數(shù)函數(shù)定義: intopen(constchar*pathname,intflags);參數(shù)說明: 參數(shù)pathname指向欲打開的文件路徑字符串。下列是參數(shù)flags所能使用的標志位:O_RDONLY以只讀方式打開文件O_WRONLY以只寫方式打開文件O_RDWR以可讀寫方式打開文件。上述三種標志位是互斥的,也就是不可同時使用,但可與下列的標志位利用OR(|)運算符組合。O_CREAT若欲打開的文件不存在則自動建立該文件。O_EXCL如果O_CREAT也被設置,此指令會去檢查文件是否存在。文件若不存在則建立該文件,否則將導致打開文件錯誤。此外,若O_CREAT與O_EXCL同時設置,并且欲打開的文件為符號連接,則會打開文件失敗。O_NOCTTY如果欲打開的文件為終端機設備時,則不會將該終端機當成進程控制終端機。O_TRUNC若文件存在并且以可寫的方式打開時,此標志位會令文件長度清為0,而原來存于該文件的資料也會消失。O_APPEND當讀寫文件時會從文件尾開始移動,也就是所寫入的數(shù)據(jù)會以附加的方式加入到文件后面。O_NONBLOCK以不可阻斷的方式打開文件,也就是無論有無數(shù)據(jù)讀取或等待,都會立即返回進程之中。O_NDELAY同O_NONBLOCK。O_SYNC以同步的方式打開文件。O_NOFOLLOW如果參數(shù)pathname所指的文件為一符號連接,則會令打開文件失敗。O_DIRECTORY如果參數(shù)pathname所指的文件并非為一目錄,則會令打開文件失敗。read()函數(shù)函數(shù)定義:ssize_tread(intfd,void*buf,size_tcount);參數(shù)說明:count是請求讀取的字節(jié)數(shù),讀上來的數(shù)據(jù)保存在緩沖區(qū)buf中,同時文件的當前讀寫位置向后移。返回值: 成功返回讀取的字節(jié)數(shù),出錯返回-1并設置errno,如果在調(diào)read之前已到達文件末尾,則這次read返回0。write()函數(shù)函數(shù)定義: ssize_twrite(intfd,void*buf,size_tcount);參數(shù)說明: write()會把參數(shù)buf所指內(nèi)存寫入count個字節(jié)到參數(shù)fd所指的文件內(nèi)。文件讀寫位置也會隨之移動。返回值: 如果順利write()會返回實際寫入的字節(jié)數(shù)。當有錯誤發(fā)生時則返回-1,錯誤代碼存入error中。多窗口進程并發(fā)本實驗需要的圖形庫是跨平臺的開發(fā)工具Qt。實現(xiàn)的功能很簡單,即運行主程序后可以彈出三個進程的可視化窗口。三個窗口都是在Qt中使用widget窗口類實現(xiàn),上面分別顯示出“Process1”、“Process2”和“Process3”。在主程序中,使用三次fork()函數(shù)分別創(chuàng)建三個子進程,其中“Process2”是“Process1”的子進程,“Process3”是“Process2”的子進程,每個子進程中都使用execv()函數(shù)執(zhí)行其對應的可視化窗口的可執(zhí)行文件。測試結(jié)果文件拷貝首先,創(chuàng)建一個源文件1.txt,其內(nèi)容為“helloworld!”,如圖1.1所示。圖1.1源文件內(nèi)容之后創(chuàng)建一個新的目的文件2.txt,內(nèi)容為空,如圖1.2所示。圖1.2新建目的文件 通過終端進入正確的目錄,編譯并執(zhí)行文件拷貝程序copy,終端顯示出字符串“Success”,表示拷貝成功,如圖1.3所示。圖1.3執(zhí)行文件拷貝命令行 再次查看目的文件2.txt,發(fā)現(xiàn)拷貝已成功,如圖1.4所示。圖1.4拷貝成功多窗口進程并發(fā)編譯并執(zhí)行包含有創(chuàng)建三個子進程的main.c文件,即可顯示出三個子進程所對應的可視化窗口,每個窗口上顯示出這是第幾個進程,效果如圖1.5所示。圖1.5多窗口進程并發(fā)效果源代碼文件拷貝#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<stdio.h>#defineSIZE1024intmain(intargc,char*argv[]){intfile1,file2;//文件描述符intnum_read,num_write;intnum_read,num_write;charbuffer[SIZE];if(argc!=3){printf("Inputformatisillegal!\n");return0;}/*打開源文件*/if((file1=open(argv[1],O_RDONLY))==-1){printf("Openerror!\n");return0;}/*創(chuàng)建目標文件*/if((file2=open(argv[2],O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR))==-1){printf("Openerror!\n");return0;}/*實現(xiàn)文件拷貝*/while((num_read=read(file1,buffer,sizeof(buffer)))>0){num_write=write(file2,buffer,num_read);}printf("Success!\n");close(file1);close(file2);return1;}多窗口進程并發(fā)#include<stdio.h>#include<unistd.h>#include<sys/types.h>#include<sys/wait.h>voidmain(){intstatus;pid_tp1,p2,p3;/*創(chuàng)建三個子進程*/if((p1=fork())==0)execv("./widget1",NULL);elseif((p2=fork())==0)execv("./widget2",NULL);elseif((p3=fork())==0)execv("./widget3",NULL);/*等待子進程結(jié)束*/waitpid(p1,(int*)0,WIFEXITED(&status));waitpid(p2,(int*)0,WIFEXITED(&status));waitpid(p3,(int*)0,WIFEXITED(&status));exit(0);}增加系統(tǒng)調(diào)用、編譯內(nèi)核課設內(nèi)容掌握系統(tǒng)調(diào)用的實現(xiàn)過程,通過編譯內(nèi)核方法,加一個新的系統(tǒng)調(diào)用,另編寫一個應用程序,調(diào)用新增加的系統(tǒng)調(diào)用。課設要求內(nèi)核編譯、生成,使用新內(nèi)核啟動;增系統(tǒng)調(diào)用實現(xiàn):文件拷貝或P、V操作。實驗環(huán)境硬件環(huán)境:MacBookAir13-inch4GBMemory1.3GHzCorei5操作系統(tǒng):Ubuntu64位15.10原配內(nèi)核:Linux-4.2.0-16-generic新編譯內(nèi)核:Linux-3.18.27具體實現(xiàn)系統(tǒng)調(diào)用的原理用戶進程不能訪問內(nèi)核所占內(nèi)存空間,也不能調(diào)用內(nèi)核函數(shù)。進程調(diào)用一個特殊的指令,這個指令會跳到一個事先定義的內(nèi)核中的一個位置。在IntelCPU中,由中斷INT0x80實現(xiàn)。(與DOS功能調(diào)用int0x21很相似)跳轉(zhuǎn)到的內(nèi)核位置叫做sysem_call。檢查系統(tǒng)調(diào)用號,這個號碼代表進程請求哪種服務。然后,它查看系統(tǒng)調(diào)用表(sys_call_table)找到所調(diào)用的內(nèi)核函數(shù)入口地址。接著,就調(diào)用函數(shù),等返回后,做一些系統(tǒng)檢查,最后返回到進程(如果這個進程時間用盡,就返回到其他進程)。編寫新的系統(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ù)此時對應內(nèi)核函數(shù)sys_open、sys_read、sys_write、sys_close函數(shù)。循環(huán)拷貝的判斷條件還是sys_read的返回值,當其大于0的時候執(zhí)行循環(huán),否則表示源文件已拷貝到了目標文件。mm_segment_t類型的變量fs的作用是在讀寫文件前得到當前fs,避免使用的緩沖區(qū)超過了用戶空間的地址范圍而報錯。編譯內(nèi)核下載新的內(nèi)核壓縮包linux-3.18.27.tar.xz,解壓到/usr/src/文件夾下;進入目錄/usr/src/linux-3.18.27;添加系統(tǒng)調(diào)用函數(shù),修改文件/kernel/sys.c如圖2.1所示;圖2.1添加系統(tǒng)調(diào)用添加系統(tǒng)調(diào)用號:322,修改文件/arch/x86/syscalls/syscall_64.tbl,如圖2.2所示;圖2.2添加系統(tǒng)調(diào)用號添加聲明到頭文件,修改文件/include/linux/syscalls.h如圖2.3所示;圖2.3添加頭文件聲明在編譯內(nèi)核之前先要安裝ncurses庫,進入超級用戶狀態(tài),使用命令#apt-getinstalllibncurses5-dev安裝;#makemrproper凈化解壓后的源代碼;#makemenuconfig對內(nèi)核選項進行配置;#makeclean刪除配置時留下的一些不用的文件;#make-j4編譯內(nèi)核和內(nèi)核模塊,使用多線程加速編譯;#makemodules_install安裝內(nèi)核模塊;#makeinstall安裝內(nèi)核;由于使用虛擬機,需輸入命令:mkinitramfs-o/boot/initrd.img-3.18.27;在終端內(nèi)使用vim對文件/boot/grub/grub.cfg進行修改,將其中的settimeout_style=hidden改為=menu,將settimeout=o改為=30,如圖2.4所示,這樣可以使系統(tǒng)啟動時可以顯示出選擇內(nèi)核的菜單;圖2.4修改文件以顯示引導菜單重新啟動,選擇進入linux-3.18.27內(nèi)核即可。測試結(jié)果進入目錄,目錄中的文件如圖2.5所示:圖2.5目錄中的文件 1.txt中的內(nèi)容為“helloworld!”,編譯并執(zhí)行test測試程序,即可完成將1.txt的內(nèi)容拷貝到2.txt中,如圖2.6所示。圖2.6測試程序成功源代碼#include<linux/unistd.h>#include<stdio.h>#include<stdlib.h>#include<asm/unistd.h>intmain(intargc,char*argv[]){intb=syscall(322,argv[1],argv[2]);printf("%d\n",b);return0;}增加字符設備驅(qū)動程序課設內(nèi)容掌握增加設備驅(qū)動程序的方法。通過模塊方法,增加一個新的設備驅(qū)動程序,其功能可以簡單。課設要求實現(xiàn)字符設備的驅(qū)動——可以輸出所輸入的字符串。具體實現(xiàn)模塊機制Linux核心是一種monolithic類型的內(nèi)核,即單一的大核心,另外一種形式是MicroKernel,核心的所有功能部件都被拆成獨立部分,這些部分之間通過嚴格的通訊機制進行聯(lián)系。Linux內(nèi)核是一個整體結(jié)構,因此向內(nèi)核添加任何東西或者刪除某些功能,都十分困難。為了解決這個問題,引入了模塊機制,從而可以動態(tài)的在內(nèi)核中添加或者刪除模塊。模塊一旦被插入內(nèi)核,就和內(nèi)核其他部分一樣。Linux內(nèi)核中的設備驅(qū)動程序是一組常駐內(nèi)存的具有特權的共享庫,是低級硬件處理例程。對用戶程序而言,設備驅(qū)動程序隱藏了設備的具體細節(jié),對各種不同設備提供了一致的接口,一般來說是把設備映射為一個特殊的設備文件,用戶程序可以像對其它文件一樣對此設備文件進行操作。Linux支持3種設備:字符設備、塊設備和網(wǎng)絡設備。設備由一個主設備號和一個次設備號標識。主設備號唯一標識了設備類型,即設備驅(qū)動程序類型,它是塊設備表或字符設備表中設備表項的索引。次設備號僅由設備驅(qū)動程序解釋,一般用于識別在若干可能的硬件設備中,I/O請求所涉及到的那個設備。典型的Linux模塊實現(xiàn)機制有如下幾步:注冊設備:在系統(tǒng)初啟或者加載模塊的時候,必須將設備登記到相應的設備數(shù)組,并返回主設備號。定義功能函數(shù):對于每一個驅(qū)動函數(shù)來說,都有一些和此設備密切相關的功能函數(shù)。以最常用的塊設備或者字符設備來說,都存在著諸如open()、read()這一類的操作。當系統(tǒng)調(diào)用這些調(diào)用時,將自動的使用驅(qū)動函數(shù)中特定的模塊來實現(xiàn)具體的操作。卸載設備:在不用這個設備時,可以將它卸載,主要是從/proc中取消這個設備的特殊文件。MakefileMakefile文件用于編譯設備驅(qū)動程序,其代碼采用的是PPT給出的通用代碼,這里不再進行贅述,也不在源代碼中列出。安裝設備驅(qū)動從終端進入存放著設備驅(qū)動程序和Makefile文件的目錄;輸入make命令,編譯設備驅(qū)動程序,可以在目錄中看到生成了各種配置文件,包括后綴名為.ko的模塊文件;輸入insmod–fmydevice.ko,加載生成mydevice.ko模塊;輸入cat/proc/devices,獲取設備驅(qū)動程序的主設備號;輸入mknod/dev/mydevicec測試結(jié)果按照上述步驟完成對驅(qū)動設備的編譯后,就可以在該目錄下看到生成的諸多設備文件和配置文件,如圖3.1所示;圖3.1編譯完成后生成的文件在終端進入測試程序所在的目錄,編譯并運行測試程序,如圖3.2所示;圖3.2編譯并運行測試程序按照提示輸入“hello”,則設備輸出的字樣也為“hello”,如圖3.3所示,測試成功。圖3.3測試結(jié)果系統(tǒng)監(jiān)控器課設內(nèi)容了解/proc文件的特點和使用方法;監(jiān)控系統(tǒng)狀態(tài),顯示系統(tǒng)中若干部件使用狀態(tài);用圖形界面實現(xiàn)系統(tǒng)監(jiān)控狀態(tài)。UI設計在最開始做的時候,我是將所有需要展示出的關于進程的項目(如進程號、名稱、占用內(nèi)存、父進程號等等)都呈現(xiàn)在一張列表(ListWidget)中,但我發(fā)現(xiàn)由于項目過多,橫向查看起來很不方便,所以我借鑒了蘋果Mac系統(tǒng)的活動監(jiān)視器界面,如圖4.1所示。圖4.1Mac系統(tǒng)的活動監(jiān)視器 可以看到,雖然都是展示有關進程的信息,但它將這些信息項分散到幾個不同的頁里,如將CPU占有率放在CPU頁,而將內(nèi)存使用率放在內(nèi)存頁等,這樣不僅方便了查看,也騰出了更多的空間放置別的相關信息。 如圖4.2所示,我的主界面也采用了TabWidget的分頁欄,CPU、Memory和System三頁中分別放置著有關CPU、內(nèi)存和系統(tǒng)相關的信息。上方的兩個按鍵分別可以實現(xiàn)殺死進程和搜索進程的功能。在最上方的About中還可以查看作者信息和退出該進程監(jiān)視器。留出的一些空間用來顯示CPU或內(nèi)存相關的一些數(shù)據(jù)(如占有率、剩余內(nèi)存、進程數(shù)等等)以及動態(tài)折線圖,所有需要動態(tài)顯示輸出字樣的地方都是采用Label實現(xiàn)的。圖4.2主界面此外,使用Search按鍵進行進程搜索時,我使用了一個對話框的形式來展示所搜索進程的信息,這樣可以使用戶的關注點更加集中,如圖4.3所示。圖4.3使用對話框展示搜索的進程信息主要功能實現(xiàn)獲取并顯示主機名實現(xiàn)思路該功能實現(xiàn)起來很簡單,主機名保存在/proc/self/root/etc/hostname文件中,只需要打開該文件并將字符串讀出來,再用Label輸出顯示在System一頁中即可。值得一提的是,整個程序中文件讀取操作的方法都是首先定義一個Qfile類型的變量tempFile,使用tempFile.setFileName(file’sname)函數(shù)打開指定文件,再使用tempFile.readLine()函數(shù)將一行字符串讀入一個Qstring變量中,最后使用tempFile.close()函數(shù)關閉文件。效果展示圖4.4顯示主機名源代碼tempFile.setFileName("/proc/self/root/etc/hostname");if(!tempFile.open(QIODevice::ReadOnly)){QMessageBox::warning(this,tr("warning"),tr("Cannotopenfilehostname!"),QMessageBox::Yes);return;}tempStr=tempFile.readLine();ui->label_Hostname->setText(tempStr); tempFile.close();顯示系統(tǒng)當前時間、持續(xù)時間和啟動時間實現(xiàn)思路Qt中提供的QDataTime類中直接包含有顯示當前系統(tǒng)時間的函數(shù)currentDataTime(),使用"yyyy-MM-ddhh:mm:ss"的格式將其顯示出來即可。 系統(tǒng)的持續(xù)時間存放在/proc/uptime文件中,該文件中存放著兩個時間數(shù)字,第一個是系統(tǒng)運行的時間,第二個是系統(tǒng)休眠的時間,我們需要的是第一個時間。將這個時間讀入一個Qstring中,由于帶有小數(shù),我們將其轉(zhuǎn)化為double型進行處理。因為此時這個時間的單位是“秒”,我們需要使用輾轉(zhuǎn)相除的方法逐步將其轉(zhuǎn)化為“小時—分鐘—秒”的格式,并將這些時間按照格式顯示出來。 啟動時間的算法是先得到上述的當前時間和持續(xù)時間,將這兩個時間化為相同的格式(如“小時—分鐘—秒”),兩者之差即為系統(tǒng)的啟動時間。此外,由于時間需要動態(tài)顯示,這里使用了定時器進行實時更新,更新周期為1秒,代碼如下:QTimer*timer=newQTimer(this);timer->setInterval(1000);connect(timer,SIGNAL(timeout()),SLOT(updatetime()));timer->start();效果展示圖4.5顯示時間源代碼QFiletempFile;QStringtempStr;tempFile.setFileName("/proc/uptime");if(!tempFile.open(QIODevice::ReadOnly)){QMessageBox::warning(this,tr("warning"),tr("Cannotopenfileuptime!"),QMessageBox::Yes);return;}tempStr=tempFile.readLine();QStringqtime_sec,qtime_hour,qtime_min;doubledtime;intntime,ntime_sec,ntime_hour,ntime_min,temp;qtime_sec=tempStr.section("",0,0);dtime=qtime_sec.toDouble();ntime=(int)dtime;ntime_hour=ntime/3600;temp=ntime-ntime_hour*3600;ntime_min=temp/60;temp=temp-ntime_min*60;ntime_sec=temp;qtime_hour=QString::number(ntime_hour);qtime_min=QString::number(ntime_min);qtime_sec=QString::number(ntime_sec);QDateTimecurtime=QDateTime::currentDateTime();QStringstr=curtime.toString("yyyy-MM-ddhh:mm:ss");ui->label_cur->setText(str);ui->label_Etime->setText(qtime_hour+"h"+qtime_min+"min"+qtime_sec+"sec");ui->label_Btime->setText("2016.3.1713:50:02");tempFile.close();顯示系統(tǒng)的版本號實現(xiàn)思路如圖4.6所示,/proc/version文件中保存著有關系統(tǒng)版本的信息。這里我們選擇輸出“Type”、“Version”和“Compiler”三個信息。首先通過index()函數(shù)找到“version”字符串的位置,將其之前的“Linux”字符串作為“Type”的輸出。之后,繼續(xù)使用index()函數(shù)找到“(”,這個位置和“version”之后的部分就是版本號的輸出。最后,仍是使用index()函數(shù)找到“gccversion”字符串和“#”的位置,這之間的字符串就是編譯器版本號的輸出,這就完成了整個三項有關系統(tǒng)版本信息的輸出。圖4.6/proc/version文件內(nèi)容效果展示圖4.7顯示系統(tǒng)版本源代碼//打開操作系統(tǒng)信息文件tempFile.setFileName("/proc/version");if(!tempFile.open(QIODevice::ReadOnly)){QMessageBox::warning(this,tr("warning"),tr("Cannotopenfileversion!"),QMessageBox::Yes);return;}tempStr=tempFile.readLine();pos=tempStr.indexOf("version");QString*os_version=newQString(tempStr.mid(0,pos-1));ui->label_SystemType->setText(*os_version);intpos1=tempStr.indexOf("(");QString*os_type=newQString(tempStr.mid(pos+8,pos1-pos-1));ui->label_SystemVersion->setText(*os_type);pos=tempStr.indexOf("gccversion");pos1=tempStr.indexOf("#");QString*gcc_info=newQString(tempStr.mid(pos+12,pos1-pos-14));ui->label_GCCVersion->setText(*gcc_info);tempFile.close();//關閉操作系統(tǒng)信息文件tempFile.setFileName("/proc/self/root/etc/hostname");if(!tempFile.open(QIODevice::ReadOnly)){QMessageBox::warning(this,tr("warning"),tr("Cannotopenfilehostname!"),QMessageBox::Yes);return;}tempStr=tempFile.readLine();ui->label_Hostname->setText(tempStr);tempFile.close();}顯示cpu的型號和主頻大小實現(xiàn)思路這里我們需要輸出CPU名稱、類型和主頻大小三個信息,這三個信息全部都在/proc/cpuinfo文件中,文件中這三個信息前面對應的項目名稱分別為“modelname:”、“vendor_id:”和“cpuMHz”。通過使用index()函數(shù)找到這三個項目名,再將位置跳過這幾個項目名的字符即可讀入對應的信息。效果展示圖4.8CPU信息注:由于電腦CPU的主頻較為特殊,常態(tài)下為1.3GHz,但在高負荷下會采用boost技術提高主頻,所以上下顯示有差異。源代碼staticintflag=0;tempFile.setFileName("/proc/cpuinfo");//打開CPU信息文件if(!tempFile.open(QIODevice::ReadOnly)){QMessageBox::warning(this,tr("warning"),tr("Thecpuinfofilecannotopen!"),QMessageBox::Yes);return;}//循環(huán)讀取文件內(nèi)容,查找需要的信息while((flag!=3)){tempStr=tempFile.readLine();if(pos=tempStr.indexOf("modelname"),pos!=-1){pos+=12;//跳過前面的"modelname:"所占用的字符QString*cpu_name=newQString(tempStr.mid(pos,tempStr.length()-12));ui->label_CPUName->setText(*cpu_name);flag++;}elseif(pos=tempStr.indexOf("vendor_id"),pos!=-1){pos+=11;//跳過前面的"vendor_id:"所占用的字符QString*cpu_type=newQString(tempStr.mid(pos,tempStr.length()-11));ui->label_CPUType->setText(*cpu_type);flag++;}elseif(pos=tempStr.indexOf("cpuMHz"),pos!=-1){pos+=10;//跳過前面的"cpuMHz:"所占用的字符QString*cpu_frq=newQString(tempStr.mid(pos,tempStr.length()-10));doublecpufrq=cpu_frq->toDouble();cpu_frq->setNum(cpufrq);ui->label_CPUFrequency->setText(*cpu_frq+"MHz");flag++;}else//跳過其他的內(nèi)容{//break;}}tempFile.close();//關閉CPU信息文件顯示所有進程的信息實現(xiàn)思路我們使用兩張ListWidget來展示所有進程的相關信息,這兩張表分別放置在CPU和Memory兩頁中,CPU頁中可以顯示pid、進程名、父進程號、運行時間,而Memory頁中可以顯示pid、進程名、狀態(tài)、優(yōu)先級、使用內(nèi)存大小。在/proc目錄下有很多以數(shù)字命名的文件夾,每一個文件夾里實際上就是一個進程的所有信息,文件夾的名字就是該進程的pid。我們需要遍歷這些文件夾,方法是使用以下兩行代碼將所有文件夾名讀入一個字符串中,使用換行符作為間隔符:QStringListqsList=qd.entryList();QStringqs=qsList.join("\n");之后用index()函數(shù)逐一讀取每個進程的pid,進入到對應的/proc/[pid]/stat文件中,這里保存著該進程的狀態(tài)、優(yōu)先級、父進程號、核心態(tài)下的使用時間、用戶態(tài)下的使用時間這六項我們需要的信息,我們將這些信息讀出來加以處理,就可以用以下的代碼創(chuàng)建表中的一行信息,即某一個進程的相關信息(以CPU頁為例):QListWidgetItem*item=newQListWidgetItem(id_of_pro+"\t"+proName+"\t"+proState+"\t"+proTime+"\t"+proppid,ui->cpulistWidget);而進程所占有的內(nèi)存大小則是在/proc/[pid]/statm文件中,該文件中以空格為分隔符的第2項信息就是該進程所占有的內(nèi)存大小,單位為KB,將它讀出來并顯示在Memory頁中即可。效果展示圖4.9Memory頁進程信息(紅線上方為信息項)圖4.10CPU頁進程信息源代碼因兩個分頁的源代碼較長且二者相似部分較多,這里只給出Memory頁的源代碼。QFiletempFile,tempFile_mem;QDirqd("/proc");QStringListqsList=qd.entryList();QStringqs=qsList.join("\n");QStringid_of_pro,tempStr;boolok;intfind_start=3;inta,b,pos;intnProPid;//進程PIDintnproMem;QStringproName;//進程名QStringproState;//進程狀態(tài)QStringproPri;//進程優(yōu)先級QStringproMem;//進程占用內(nèi)存/*QListWidgetItem*title=newQListWidgetItem("PID\t"+"Name\t"+"\t"+"State\t"+"Priority\t"+"Usedmemory\t",ui->memlistWidget);*/QListWidgetItem*title=newQListWidgetItem("PID\t"+QString::fromUtf8("Name")+"\t\t"+QString::fromUtf8("State")+"\t"+QString::fromUtf8("Priority")+"\t"+QString::fromUtf8("Usedmemory"),ui->memlistWidget);//循環(huán)讀取進程while(1){//獲取進程PIDa=qs.indexOf("\n",find_start);b=qs.indexOf("\n",a+1);find_start=b;id_of_pro=qs.mid(a+1,b-a-1);nProPid=id_of_pro.toInt(&ok,10);if(!ok){break;}//打開PID所對應的進程狀態(tài)文件tempFile.setFileName("/proc/"+id_of_pro+"/stat");if(!tempFile.open(QIODevice::ReadOnly)){QMessageBox::warning(this,tr("warning"),tr("Cannotopenpidstat!"),QMessageBox::Yes);return;}tempStr=tempFile.readLine();if(tempStr.length()==0){break;}a=tempStr.indexOf("(");b=tempStr.indexOf(")");proName=tempStr.mid(a+1,b-a-1);proName.trimmed();//刪除兩端的空格proState=tempStr.section("",2,2);proPri=tempStr.section("",17,17);//proMem=tempStr.section("",22,22);tempFile_mem.setFileName("/proc/"+id_of_pro+"/statm");//process'smemoryinfoif(!tempFile_mem.open(QIODevice::ReadOnly)){QMessageBox::warning(this,tr("warning"),tr("Cannotopenpidstatm!"),QMessageBox::Yes);return;}tempStr=tempFile_mem.readLine();if(tempStr.length()==0){break;}proMem=tempStr.section("",1,1);nproMem=proMem.toInt();if(nproMem<0)nproMem=-nproMem;nproMem=nproMem*4;proMem=QString::number(nproMem,10);tempFile_mem.close();if(proName.length()>=11){QListWidgetItem*item=newQListWidgetItem(id_of_pro+"\t"+proName+"\t"+proState+"\t"+proPri+"\t"+proMem+"KB",ui->memlistWidget);}else{QListWidgetItem*item=newQListWidgetItem(id_of_pro+"\t"+proName+"\t\t"+proState+"\t"+proPri+"\t"+proMem+"KB",ui->memlistWidget);}}tempFile.close();//關閉該PID進程的狀態(tài)文件通過pid或進程名查詢或殺死進程實現(xiàn)思路對于查詢和刪除進程這兩個功能,使用pid來完成是最簡單的,但卻不太符合常規(guī)用戶的使用習慣,使用進程名顯然更加方便。所以我使用了一個checkbox來選擇是使用pid還是進程名來查詢或者殺死進程,如圖4.11所示。如果用戶誤將兩者都打勾,則會提示“illegallycheck”的字樣。圖4.11使用checkbox實現(xiàn)兩種查詢或殺死進程的方法如果選擇了使用pid來實現(xiàn)功能,則將這個pid與/proc文件夾中的所有pid進行比對,如果相同,則進入到該文件夾中利用4.3.5中的方法來獲取相關的信息,并通過另一個對話框顯示出來。如果要殺死該進程,只需使用以下語句即可,其中prokill為輸入的pid:system("kill"+prokill.toLatin1());如果選擇使用進程名來實現(xiàn)功能,則需要使用類似4.3.5中的方法將這個進程名與每一個/proc/[pid]/stat中的進程名比對,找到了匹配的結(jié)果后,將這個進程的pid記錄下來,然后就轉(zhuǎn)化為了使用pid查詢或殺死進程的方法了。效果展示使用pid來殺死firefox進程,其pid=5308:圖4.12使用pid殺死firefox進程前 使用pid殺死后,顯示“Success”,可以看到左邊的Firefox已關閉;圖4.13使用pid殺死firefox進程后使用進程名殺死firefox進程:圖4.14使用進程名殺死firefox進程使用pid查詢firefox進程,pid=5442;圖4.15使用pid查詢firefox進程使用進程名查詢firefox進程,二者結(jié)果相同;圖4.16使用進程名查詢firefox進程當checkbox重復選中時,提示錯誤。圖4.17重復選中時的錯誤提示源代碼殺死進程:QStringprokill=ui->killlineEdit->text().trimmed();if(ui->checkBox_pid->isChecked()&&!(ui->checkBox_name->isChecked())){system("kill"+prokill.toLatin1());QMessageBox::warning(this,tr("ok"),QString::fromUtf8("Success!"),QMessageBox::Yes);ui->killlineEdit->clear();}if(!(ui->checkBox_pid->isChecked()^ui->checkBox_name->isChecked())){QMessageBox::warning(this,tr("warning"),QString::fromUtf8("Illegalcheck!"),QMessageBox::Yes);}if(!ui->checkBox_pid->isChecked()&&(ui->checkBox_name->isChecked())){QStringproName;inta,b;intfind_start=3;intnProPid;boolok;QFiletempFile;QDirqd("/proc");QStringListqsList=qd.entryList();QStringqs=qsList.join("\n");QStringid_of_pro,tempStr;while(proName!=prokill){a=qs.indexOf("\n",find_start);b=qs.indexOf("\n",a+1);find_start=b;id_of_pro=qs.mid(a+1,b-a-1);nProPid=id_of_pro.toInt(&ok,10);if(!ok){QMessageBox::warning(this,tr("warning"),QString::fromUtf8("Cannotfindit!"),QMessageBox::Yes);break;}//打開PID所對應的進程狀態(tài)文件tempFile.setFileName("/proc/"+id_of_pro+"/stat");if(!tempFile.open(QIODevice::ReadOnly)){QMessageBox::warning(this,tr("warning"),tr("Cannotopenpidstat!"),QMessageBox::Yes);return;}tempStr=tempFile.readLine();if(tempStr.length()==0){break;}a=tempStr.indexOf("(");b=tempStr.indexOf(")");proName=tempStr.mid(a+1,b-a-1);tempFile.close();}system("kill"+id_of_pro.toLatin1());QMessageBox::warning(this,tr("ok"),QString::fromUtf8("Success!"),QMessageBox::Yes);ui->killlineEdit->clear();}查詢進程voidMainWindow::on_srchBtn_clicked(){//QStringprosrch=ui->srchlineEdit->text.trimmed();if(ui->checkBox_pid->isChecked()&&!(ui->checkBox_name->isChecked())){QStringid_of_pro=ui->srchlineEdit->text().trimmed();info.get_pid(id_of_pro);info.exec();ui->srchlineEdit->clear();}if(!(ui->checkBox_pid->isChecked()^ui->checkBox_name->isChecked())){QMessageBox::warning(this,tr("warning"),QString::fromUtf8("Illegalcheck!"),QMessageBox::Yes);}if(!ui->checkBox_pid->isChecked()&&(ui->checkBox_name->isChecked())){QStringprosrch=ui->srchlineEdit->text().trimmed();QStringproName;inta,b;intfind_start=3;intnProPid;boolok;QFiletempFile;QDirqd("/proc");QStringListqsList=qd.entryList();QStringqs=qsList.join("\n");QStringid_of_pro,tempStr;while(proName!=prosrch){a=qs.indexOf("\n",find_start);b=qs.indexOf("\n",a+1);find_start=b;id_of_pro=qs.mid(a+1,b-a-1);nProPid=id_of_pro.toInt(&ok,10);if(!ok){QMessageBox::warning(this,tr("warning"),QString::fromUtf8("Cannotfindit!"),QMessageBox::Yes);break;}//打開PID所對應的進程狀態(tài)文件tempFile.setFileName("/proc/"+id_of_pro+"/stat");if(!tempFile.open(QIODevice::ReadOnly)){QMessageBox::warning(this,tr("warning"),tr("Cannotopenpidstat!"),QMessageBox::Yes);return;}tempStr=tempFile.readLine();if(tempStr.length()==0){break;}a=tempStr.indexOf("(");b=tempStr.indexOf(")");proName=tempStr.mid(a+1,b-a-1);tempFile.close();}info.get_pid(id_of_pro);info.exec();ui->srchlineEdit->clear();}}voidinfoDlg::get_pid(QStringpid){QStringid_of_pro=pid;QFiletempFile;QStringtempStr;QDirqd("/proc");QStringListqsList=qd.entryList();QStringqs=qsList.join("\n");boolok;inta,b;intnProPid;//進程PIDintnproMem;QStringproName;//進程名QStringproState;//進程狀態(tài)QStringproPri;//進程優(yōu)先級QStringproMem;//進程占用內(nèi)存QStringproTime1,proTime2,proTime;QStringproppid;//獲取進程PIDnProPid=id_of_pro.toInt(&ok,10);//打開PID所對應的進程狀態(tài)文件tempFile.setFileName("/proc/"+id_of_pro+"/stat");if(!tempFile.open(QIODevice::ReadOnly)){QMessageBox::warning(this,tr("warning"),tr("Cannotopenpidstat!"),QMessageBox::Yes);return;}tempStr=tempFile.readLine();a=tempStr.indexOf("(");b=tempStr.indexOf(")");proName=tempStr.mid(a+1,b-a-1);proName.trimmed();//刪除兩端的空格proState=tempStr.section("",2,2);proPri=tempStr.section("",17,17);//proMem=tempStr.section("",22,22);proppid=tempStr.section("",3,3);proTime1=tempStr.section("",12,12);proTime2=tempStr.section("",13,13);intntime1=proTime1.toInt();intntime2=proTime2.toInt();intntime=ntime1+ntime2;proTime=QString::number(ntime);tempFile.close();tempFile.setFileName("/proc/"+id_of_pro+"/statm");//process'smemoryinfoif(!tempFile.open(QIODevice::ReadOnly)){QMessageBox::warning(this,tr("warning"),tr("Cannotopenpidstatm!"),QMessageBox::Yes);return;}tempStr=tempFile.readLine();proMem=tempStr.section("",1,1);nproMem=proMem.toInt();if(nproMem<0)nproMem=-nproMem;nproMem=nproMem*4;proMem=QString::number(nproMem,10);tempFile.close();ui->label_name->setText(proName);ui->label_ppid->setText(proppid);ui->label_priority->setText(proPri);ui->label_mem->setText(proMem+"KB");ui->label_state->setText(proState);ui->label_time->setText(proTime);}顯示當前內(nèi)存和交換分區(qū)使用情況實現(xiàn)思路這部分同樣需要計時器實時更新。如圖4.18所示,在/proc/meminfo文件中,每一個信息項前面都已經(jīng)表明了這個信息項的名稱,所以我們只需要使用index()函數(shù)對這些名稱進行檢索、定位后選取后面的數(shù)字作為需要的信息即可。之后將這些信息進行轉(zhuǎn)換為int型,再進行一些運算,如對于可直接讀出的總內(nèi)存和空閑內(nèi)存,兩者相減得到的是已使用內(nèi)存,用已使用內(nèi)存比上總內(nèi)存即是內(nèi)存的使用率。圖4.18meminfo內(nèi)容效果展示圖4.19內(nèi)存和交換分區(qū)使用情況源代碼tempFile.setFileName("/proc/meminfo");//打開內(nèi)存信息文件if(!tempFile.open(QIODevice::ReadOnly)){QMessageBox::warning(this,tr("warning"),tr("Cannotopenmeminfo!"),QMessageBox::Yes);return;}QStringmemTotal;QStringmemFree;QStringmemUsed;QStringmemRate;QStringswapTotal;QStringswapFree;QStringswapUsed;QStringswapRate;intnMemTotal,nMemFree,nMemUsed,nMemrate,nSwapTotal,nSwapFree,nSwapUsed,nSwapRate;while(1){tempStr=tempFile.readLine();pos=tempStr.indexOf("MemTotal");if(pos!=-1){memTotal=tempStr.mid(pos+10,tempStr.length()-13);memTotal=memTotal.trimmed();nMemTotal=memTotal.toInt()/1024;}elseif(pos=tempStr.indexOf("MemFree"),pos!=-1){memFree=tempStr.mid(pos+9,tempStr.length()-12);memFree=memFree.trimmed();nMemFree=memFree.toInt()/1024;}elseif(pos=tempStr.indexOf("SwapTotal"),pos!=-1){swapTotal=tempStr.mid(pos+11,tempStr.length()-14);swapTotal=swapTotal.trimmed();nSwapTotal=swapTotal.toInt()/1024;}elseif(pos=tempStr.indexOf("SwapFree"),pos!=-1){swapFree=tempStr.mid(pos+10,tempStr.length()-13);swapFree=swapFree.trimmed();nSwapFree=swapFree.toInt()/1024;break;}}nMemUsed=nMemTotal-nMemFree;nSwapUsed=nSwapTotal-nSwapFree;nMemrate=nMemUsed*100/nMemTotal;nSwapRate=nSwapUsed*100/nSwapTotal;memUsed=QString::number(nMemUsed,10);memFree=QString::number(nMemFree,10);memTotal=QString::number(nMemTotal,10);memRate=QString::number(nMemrate,10);swapUsed=QString::number(nSwapUsed,10);swapFree=QString::number(nSwapFree,10);swapTotal=QString::number(nSwapTotal,10);swapRate=QString::number(nSwapRate,10);ui->label_RAM_Used->setText(memUsed+"MB");ui->label_RAM_Left->se
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年新型建筑施工中介服務協(xié)議版B版
- 2024-2030年中國客戶關系管理系統(tǒng)項目可行性研究報告
- 2024-2030年中國天然橡膠行業(yè)發(fā)展分析及投資風險研究報告
- 2024-2030年中國復合保溫銅水管融資商業(yè)計劃書
- 2024-2030年中國基金小鎮(zhèn)行業(yè)運營管理模式分析及投資規(guī)劃研究報告版
- 眉山藥科職業(yè)學院《有限元基礎與應用實驗》2023-2024學年第一學期期末試卷
- 2024年煤礦物資供應合同范本
- 呂梁學院《行為生態(tài)學》2023-2024學年第一學期期末試卷
- 2024年版簡單建設工程結(jié)算協(xié)議書模板
- 2025水上運輸合同范本
- 【MOOC】大學攝影-河南理工大學 中國大學慕課MOOC答案
- 執(zhí)紀審查業(yè)務專題培訓
- 信息安全意識培訓課件
- Python試題庫(附參考答案)
- 道法第二單元 成長的時空 單元測試 2024-2025學年統(tǒng)編版道德與法治七年級上冊
- MOOC 理解馬克思-南京大學 中國大學慕課答案
- 海洋的前世今生智慧樹知到期末考試答案2024年
- 預算與預算法課件
- (完整版)CMMI3級--EPG的問題及答案
- 用友銀企聯(lián)云服務ppt課件
- 同城票據(jù)結(jié)算業(yè)務
評論
0/150
提交評論