操作系統(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),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

課程設(shè)計(jì)報(bào)告課程名稱:計(jì)算機(jī)操作系統(tǒng)專業(yè)班級: 學(xué)號: 姓名:指導(dǎo)教師:報(bào)告日期:計(jì)算機(jī)科學(xué)與技術(shù)學(xué)院目錄TOC\o"1-2"\h\z\u1 實(shí)驗(yàn)?zāi)康?.4.3。設(shè)備驅(qū)動(dòng)程序安裝makeclean,清除make產(chǎn)生的殘留make,重新調(diào)用Makefile編譯設(shè)備驅(qū)動(dòng)程序insmod-fMyDeviceDriver.ko,加載生成的MyDeviceDriver.ko模塊cat/proc/devices,獲取設(shè)備驅(qū)動(dòng)程序的主設(shè)備號⑤mknod/dev/MyDeviceDriverc2500,創(chuàng)建設(shè)備文件,250為主設(shè)備號,0為從設(shè)備號測試驅(qū)動(dòng)程序此設(shè)備驅(qū)動(dòng)程序?qū)崿F(xiàn)的功能是將一個(gè)字符串中內(nèi)容拷貝到另外一個(gè)字符串中。測試程序編寫完成后,在終端輸入gcctest.c-otest進(jìn)行編譯。測試結(jié)果如下:詳細(xì)代碼見REF_Ref416435358\r\h4.3.3。源代碼設(shè)備驅(qū)動(dòng)程序#include<linux/module.h>#include<linux/types.h>#include<linux/fs.h>#include<linux/sched.h>#include<linux/init.h>#include<linux/cdev.h>#include<linux/slab.h>#include<asm/uaccess.h>#defineDEV_SIZE102400//設(shè)備申請的最大內(nèi)存空間structDevice{char*data;//數(shù)組指針,用于存放從用戶讀入的數(shù)據(jù)longsize;//存儲的數(shù)據(jù)長度}*devp;structcdevcdev;//字符設(shè)備結(jié)構(gòu)體staticintdevNum_major=0;//主設(shè)備號變量//對應(yīng)用戶態(tài)的lseekstaticloff_tmy_llseek(structfile*offset,intwhence){ loff_tcfo=0;//文件當(dāng)前偏移量,currentswitch(whence){case0://SEEK_SETcfo=offset;break; case1://SEEK_CURcfo=file->f_pos+offset;break; case2://SEEK_ENDcfo=DEV_SIZE-1+offset;break;}if((cfo<0)||(cfo>DEV_SIZE))//文件偏移量越界 return-EINVAL;file->f_pos=cfo;returncfo;}//對應(yīng)用戶態(tài)的read,寫數(shù)據(jù)到用戶空間staticssize_tmy_read(structfile*file,char__user*buf,size_tcount,loff_t*p_cfo){ intval=0; structDevice*dev=file->private_data;//設(shè)備描述結(jié)構(gòu)體指針,獲取設(shè)備信息 if(copy_to_user(buf,(void*)(dev->data+*p_cfo),count))//如果成功返回0;如果失敗,返回未完成copy的長度 val=-EFAULT; else { *p_cfo+=count;//copy成功,文件偏移量加上count val=count; } returnval;}//對應(yīng)用戶態(tài)的write,從用戶空間讀入數(shù)據(jù)staticssize_tmy_write(structfile*file,constchar__user*buf,size_tcount,loff_t*p_cfo){ intval=0; structDevice*dev=file->private_data; if(copy_from_user(dev->data+*p_cfo,buf,count))//如果成功返回0;如果失敗,返回未完成copy的長度 val=-EFAULT; else { *p_cfo+=count;//copy成功,文件偏移量加上count val=count; } returnval;}staticintmy_open(structinode*inode,structfile*file){file->private_data=devp;return0;}structfops={ .owner=THIS_MODULE, .llseek=my_llseek, .read=my_read, .write=my_write, .open=my_open,};intinit_module(void){ intdev_num; dev_num=register_chrdev(0,"MyDeviceDriver",&fops); if(dev_num<0){ printk(KERN_INFO"MyDeviceDriver:FAILtogetmajornumber\n"); returndev_num; } if(devNum_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個(gè)字符設(shè)備 //為設(shè)備描述結(jié)構(gòu)體分配內(nèi)存 devp=kmalloc(sizeof(structDevice),GFP_KERNEL); if(!devp) { dev_num=-ENOMEM; printk(KERN_INFO"MyDeviceDriver:FAILtogetmemory\n"); returndev_num; }(*devp).size=DEV_SIZE;(*devp).data=kmalloc(DEV_SIZE,GFP_KERNEL);memset((*devp).data,0,(*devp).size);//初始化為0 return0;}voidcleanup_module(void){ cdev_del(&cdev);//注銷設(shè)備 kfree(devp);//注銷設(shè)備結(jié)構(gòu)體 kfree((*devp).data);//注銷設(shè)備內(nèi)存空間 unregister_chrdev(devNum_major,"MyDeviceDriver");//卸載主設(shè)備號}MODULE_LICENSE("GPL");驅(qū)動(dòng)程序測試程序#include<stdio.h>#include<stdlib.h>#include<linux/fcntl.h>#defineBUFFER_SIZE102400intmain(void){ intdev,i=0; charc; charsource[BUFFER_SIZE];//寫入MyDeviceDriver設(shè)備的內(nèi)容 chargoal[BUFFER_SIZE];//MyDeviceDriver設(shè)備的內(nèi)容讀入到該goal中 printf("inputthestringyouwanttowriteinyourdevice:\n"); while((c=getchar())!='\n') { source[i++]=c; } printf("\n"); if((dev=open("/dev/MyDeviceDriver",O_RDWR))==-1)//打開MyDeviceDriver設(shè)備失敗 printf("FAILtoopenMyDeviceDriver!\n"); else//成功 printf("SUCCESStoopenMyDeviceDriver!\n"); printf("source:\n%s\n\n",source); write(dev,source,sizeof(source));//把source中的內(nèi)容寫入MyDeviceDriver設(shè)備 lseek(dev,0,SEEK_SET);//把文件指針定位到文件開始的位置 read(dev,goal,sizeof(source));//把MyDeviceDriver設(shè)備中的內(nèi)容讀入到goal中 printf("goal:\n%s\n\n",goal); return0;}實(shí)驗(yàn)四實(shí)驗(yàn)四有兩個(gè)選做題目,分別是proc文件監(jiān)控系統(tǒng)和小型文件系統(tǒng),本次實(shí)驗(yàn)我選擇的題目是proc文件監(jiān)控系統(tǒng)。實(shí)驗(yàn)要求了解/proc文件的特點(diǎn)和使用方法;監(jiān)控系統(tǒng)狀態(tài),顯示系統(tǒng)中若干部件使用狀態(tài);用圖形界面實(shí)現(xiàn)系統(tǒng)監(jiān)控狀態(tài)。具體實(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ù)對象化為文件形式進(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)的版本號,與之相關(guān)的proc文件為/proc/sys/kernel/ostype和/proc/sys/kernel/osrelease;顯示CPU的型號和主頻大小,與之相關(guān)的proc文件為/proc/cpuinfo;⑥通過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)先級等,與之相關(guān)的proc文件為/proc/(pid)/stat,/proc/(pid)/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ī)名用fopen函數(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)到目前為止持續(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)的版本號從/proc/sys/kernel/ostype和/proc/sys/kernel/osrelease中讀取系統(tǒng)類型(比如linux)和系統(tǒng)內(nèi)核版本號,處理方法和獲取系統(tǒng)運(yùn)行時(shí)間的方法一樣。得到系統(tǒng)類型和系統(tǒng)內(nèi)核版本號之后,調(diào)用QString類的方法arg將兩個(gè)字符串連接起來,再輸出顯示即可。=5\*GB3⑤顯示CPU的型號和主頻大小打開/proc/cpuinfo文件后發(fā)現(xiàn)CPU有四個(gè),相同的型號,不同的主頻,后來才弄清楚所謂的四個(gè)CPU是CPU的四個(gè)核心,而“主頻”并不是主頻,而是當(dāng)前時(shí)刻該核心所使用的CPU核心頻率,隨時(shí)間而變化的。弄清楚文件中的內(nèi)容的含義之后,開始處理/proc/cpuinfo,從中讀取CPU的型號和頻率。處理這個(gè)文件沒有用到fopen等函數(shù),而是使用了Qt自帶的兩個(gè)類Q,定義一個(gè)QFile類型的變量file,并用路徑名“/proc/cpuinfo”初始化該變量,其作用是以只讀方式打開文件/proc/cpuinfo,然后以file的地址作為參數(shù)初始化QTextStream類型的變量stream,其作用是將/proc/cpuinfo文件中的內(nèi)容以字符流的形式存入變量stream中,相當(dāng)于一個(gè)文本流。由于CPU的型號是一樣的,所以只讀取第一個(gè)型號名稱即可,根據(jù)CPU型號名稱所在的行,采用while循環(huán)讀取stream中的內(nèi)容,每次讀取一行,當(dāng)行數(shù)等于CPU型號所在行時(shí),將讀取出的一行賦值給一個(gè)QString類型的變量,再調(diào)用QString的方法mid截取CPU型號名稱,()關(guān)閉四個(gè)核心的主頻處理方法和CPU型號的處理方法一致,參照上述步驟即可。⑥通過pid或者進(jìn)程名查詢一個(gè)進(jìn)程,并顯示該進(jìn)程的詳細(xì)信息,提供殺掉該進(jìn)程的功能在獲取所有進(jìn)程信息的時(shí)候,獲取到的所有信息已經(jīng)被存儲在一個(gè)全局結(jié)構(gòu)體數(shù)組變量中了,所以查詢的時(shí)候,先獲取輸入lineEdit中的文本(QString類型),然后將文本與全局結(jié)構(gòu)體數(shù)組變量的每一個(gè)數(shù)組元素的name成員和pid成員作比較,若相等,說明待查詢的進(jìn)程存在,將該進(jìn)程的詳細(xì)信息輸出即可。殺死進(jìn)程前先要獲取將要被殺死進(jìn)程的名稱或者pid,而且該進(jìn)程必須存在于/proc目錄下,即先查詢一次待殺死的進(jìn)程,處理方法如上所述。Linux系統(tǒng)提供了kill、pkill等殺死進(jìn)程的命令,pkill通過pid殺死進(jìn)程,kill通過進(jìn)程名稱殺死進(jìn)程。通過將lineEdit中的內(nèi)容和kill或pkill組成終端命令,然后調(diào)用system函數(shù)執(zhí)行這些命令即可殺死相應(yīng)的進(jìn)程。=7\*GB3⑦顯示系統(tǒng)所有進(jìn)程的一些信息,包括pid、ppid、占用內(nèi)存大小、優(yōu)先級等系統(tǒng)的進(jìn)程眾多,且進(jìn)程號從1到幾萬的都有,如果從1開始遍歷訪問,效率就會很低。所以本次實(shí)驗(yàn)我采用的是Linux中對目錄進(jìn)行操作的函數(shù)opendir(),readdir()。這兩個(gè)目錄操作函數(shù)在上學(xué)期的操作系統(tǒng)第三次課程實(shí)驗(yàn)中已經(jīng)學(xué)習(xí)使用過,所以再次使用沒遇到多大的障礙。實(shí)現(xiàn)思路為:聲明一個(gè)DIR類型的指針dir,用opendir函數(shù)打開/proc目錄,返回值賦值給dir,然后將dir作為函數(shù)readdir的參數(shù),readdir函數(shù)返回值復(fù)制給dirent結(jié)構(gòu)體指針ptr。ptr指向的結(jié)構(gòu)體包含d_namechar數(shù)組成員,即文件或者目錄名,將d_name數(shù)組的0號元素分別和字符‘1’、‘9’比較,若處于這兩者之間,則表明該文件或者目錄是進(jìn)程目錄,以該目錄名為參數(shù)調(diào)用獲取進(jìn)程詳細(xì)信息的函數(shù)read_proc。在read_proc函數(shù)中,使用格式化輸出函數(shù)sprintf將參數(shù)目錄名c_pid對應(yīng)目錄下的文件stat的路徑輸出到char數(shù)組中,再調(diào)用C++的類ifstream,聲明一個(gè)ifstream類性的變量meminfo,用初始化meminfo,然后用析取器(>>)從meminfo中輸入數(shù)據(jù)到結(jié)構(gòu)體數(shù)組procInfo的每個(gè)元素的成員變量中,析取器(>>)會自動(dòng)忽略空字符。所需要的進(jìn)程信息并不是連續(xù)存放在stat文件中的,中間包含有其他不需要顯示的進(jìn)程信息,解決方法是定義一個(gè)string類型的變量temp,根據(jù)stat文件中的信息存放順序,將所有不需要的進(jìn)程信息全部輸入到temp中。此外還要注意一個(gè)問題,進(jìn)程名稱帶有括號“()”,所以需要將括號去掉,解決方法是使用string類的方法substr,該函數(shù)的參數(shù)有兩個(gè),一個(gè)是想截取的字符串首字符在原字符串中的位置,第二個(gè)參數(shù)是想截取的字符串末尾字符后面一個(gè)字符,在這里就是“)”。處理完畢之后,所需要的關(guān)于進(jìn)程c_pid的詳細(xì)信息都存儲在全局結(jié)構(gòu)體數(shù)組procInfo的元素中了。循環(huán)采用上述思路,直到所有進(jìn)程目錄都被處理完畢,所有的進(jìn)程信息就都存儲在了全局結(jié)構(gòu)體數(shù)組procInfo中,然后用定時(shí)器觸發(fā)定時(shí)更新全局結(jié)構(gòu)體數(shù)組procInfo中的內(nèi)容。⑧CPU使用率的圖形化顯示由于需要畫出CPU使用率兩分鐘內(nèi)的歷史記錄曲線,所以需要計(jì)算并存儲120個(gè)連續(xù)時(shí)刻的CPU利用率。定義一個(gè)全局QList變量yList,用于存放CPU使用率。在CPURate函數(shù)中調(diào)用add_point函數(shù),add_point的參數(shù)是cpuRate。在函數(shù)add_point中,首先判斷yList的大小,若大于120,則把yList的隊(duì)首元素刪除,保證yList的元素個(gè)數(shù)恒等于120;若等于0,則將yList前119個(gè)元素初始化為0,這樣的話,CPU歷史記錄曲線就會從右邊向左邊逐漸顯示出來;若大于等于1,則在yList末尾插入新的cpuRate,然后調(diào)用UpdateCPULine函數(shù)畫出記錄曲線。得到CPU使用率之后,在函數(shù)UpdateCPULine中畫圖。先在QPixmap類型的變量pix上畫曲線,pix相當(dāng)于一塊畫布,然后再把pix添加到label標(biāo)簽上。pix的背景色設(shè)置為藍(lán)色,然后定義一個(gè)QPainter類painter,painter的畫圖設(shè)備就是pix,定義QPen畫筆pen,畫筆顏色設(shè)置為紅色,畫筆寬度為2個(gè)像素,設(shè)置完成后,以yList中存儲的cpuRate為縱坐標(biāo),以yList的元素下標(biāo)為橫坐標(biāo),并根據(jù)坐標(biāo)軸單位長度所占實(shí)際像素個(gè)數(shù)稍微調(diào)整一下每個(gè)點(diǎn)的橫縱坐標(biāo),然后調(diào)用painter的drawLine方法畫出這些點(diǎn)并依次連接起來,就得到了2分鐘內(nèi)的CPU使用率歷史記錄曲線,而且歷史記錄曲線可以隨著時(shí)間從右向左更新。⑨內(nèi)存和交換分區(qū)的使用率的圖形化顯示由于需要畫出內(nèi)存使用率兩分鐘內(nèi)的歷史記錄曲線,所以需要計(jì)算并存儲120個(gè)連續(xù)時(shí)刻的內(nèi)存利用率。定義一個(gè)全局QList變量yList1,用于存放內(nèi)存使用率。在MemRate函數(shù)中調(diào)用add_point函數(shù),add_point的參數(shù)是memRate。在函數(shù)add_point中,首先判斷yList1的大小,若大于120,則把yList1的隊(duì)首元素刪除,保證yList1的元素個(gè)數(shù)恒等于120;若等于0,則將yList1前119個(gè)元素初始化為0,這樣的話,內(nèi)存使用率歷史記錄曲線就會從右邊向左邊逐漸顯示出來;若大于等于1,則在yList1末尾插入新的memRate,然后調(diào)用UpdateMemLine函數(shù)畫出記錄曲線。得到內(nèi)存使用率之后,在函數(shù)UpdateMemLine中畫圖。先在QPixmap類型的變量pix上畫曲線,pix相當(dāng)于一塊畫布,然后再把pix添加到label標(biāo)簽上。pix的背景色設(shè)置為藍(lán)色,然后定義一個(gè)QPainter類painter,painter的畫圖設(shè)備就是pix,定義QPen畫筆pen,畫筆顏色設(shè)置為紅色,畫筆寬度為2個(gè)像素,設(shè)置完成后,以yList1中存儲的memRate為縱坐標(biāo),以yList1的元素下標(biāo)為橫坐標(biāo),并根據(jù)坐標(biāo)軸單位長度所占實(shí)際像素個(gè)數(shù)稍微調(diào)整一下每個(gè)點(diǎn)的橫縱坐標(biāo),然后調(diào)用painter的drawLine方法畫出這些點(diǎn)并依次連接起來,就得到了2分鐘內(nèi)的內(nèi)存使用率歷史記錄曲線,而且歷史記錄曲線可以隨著時(shí)間從右向左更新。⑩在狀態(tài)欄顯示當(dāng)前時(shí)間調(diào)用QDateTime的方法currentDateTime獲取當(dāng)前時(shí)間time,time是一個(gè)QDateTime類型的變量,然后調(diào)用QDateTime的方法toString把time轉(zhuǎn)化成格式為yyyy-MM-ddhh:mm:ssdddd的QString字符串,再在主窗口的狀態(tài)欄顯示輸出即可。?在狀態(tài)欄顯示當(dāng)前CPU使用率CPU的使用率是指CPU的使用時(shí)間和CPU總時(shí)間的比值。因?yàn)?proc/stat文件中的所有值都是從系統(tǒng)啟動(dòng)開始累計(jì)到當(dāng)前時(shí)刻,所以計(jì)算CPU使用率時(shí)需要取兩個(gè)采樣點(diǎn),利用兩個(gè)點(diǎn)的差值計(jì)算CPU使用率,此次實(shí)驗(yàn)采樣方法是每隔1秒采樣一次。CPU使用率的計(jì)算公式為cpuRate=100.0-(idle2-idle1)*100.0/(total2-total1)。定義一個(gè)全局結(jié)構(gòu)體CPU_USE,具體定義如下:typedefstructCPU_USE{charname[16];//cpuunsignedintuser;unsignedintnice;unsignedintsystem;unsignedintidle;unsignedintiowait;unsignedintirq;unsignedintsoftirq;}cpu_use;CPU總時(shí)間的值等于結(jié)構(gòu)體CPU_USE中7個(gè)unsignedint類型的成員值之和。計(jì)算之前,調(diào)用get_cpu_use_stat函數(shù)獲取一個(gè)CPU狀態(tài),sleep一秒后再調(diào)用該函數(shù)獲取第二個(gè)CPU狀態(tài),然后用上述CPU使用率計(jì)算公式計(jì)算即可。?在狀態(tài)欄顯示當(dāng)前內(nèi)存使用情況內(nèi)存使用率是指已使用的內(nèi)存和總內(nèi)存的比值。內(nèi)存使用率的計(jì)算公式為:memRate=(total–(free+buffers+cached))*100.0/total。定義一個(gè)全局結(jié)構(gòu)體MEM_USE,具體定義如下:typedefstructMEM_USE{unsignedlongtotal;unsignedlongfree;unsignedlongbuffers;unsignedlongcached;}mem_use;該結(jié)構(gòu)體中的成員的值都來自文件/proc/meminfo,聲明一個(gè)ifstream類性的變量meminfo,用/proc/meminfo初始化meminfo,然后用析取器(>>)從meminfo中輸入數(shù)據(jù)到結(jié)構(gòu)體mem_use的成員變量中,析取器(>>)會自動(dòng)忽略空字符。所需要的內(nèi)存數(shù)據(jù)信息并不是連續(xù)存放在/proc/meminfo文件中的,中間包含有其他不需要的內(nèi)存數(shù)據(jù)信息,解決方法是定義一個(gè)string類型的變量str,根據(jù)/proc/meminfo文件中的信息存放順序,將所有不需要的內(nèi)存數(shù)據(jù)信息全部輸入到str中。得到內(nèi)存使用的數(shù)據(jù)信息之后,使用上述內(nèi)存使用率計(jì)算公式計(jì)算即可。?用新線程運(yùn)行一個(gè)其他程序在主窗口中添加一個(gè)lineEdit控件,獲取該控件中輸入的程序名稱,然后調(diào)用QProcess類的start方法運(yùn)行該程序。?關(guān)機(jī)功能由于關(guān)機(jī)功能需要輸入密碼獲取root權(quán)限,所以需要想方法在點(diǎn)擊關(guān)機(jī)按鈕后輸入密碼。定義一個(gè)QString類型的變量passWord,調(diào)用類QInputDialog的方法getText,會彈出一個(gè)對話框提示輸入密碼,該方法的返回值即為密碼,將返回值賦值給passWord變量;當(dāng)對話框的OK按鈕被點(diǎn)擊時(shí),用QString("echo%1|sudo-Sshutdown-hnow").arg(passWord)初始化QString類型的變量sudo,再把sudo轉(zhuǎn)換成char*類型,然后調(diào)用system函數(shù)執(zhí)行關(guān)機(jī)命令。(4)界面設(shè)計(jì)新建一個(gè)QtWidgetsApplication工程,用setWindowTitle函數(shù)將主窗口的標(biāo)題改為“proc進(jìn)程管理器”,設(shè)置窗口的初始大小為(650,500),初始位置為顯示屏左上角,即坐標(biāo)原點(diǎn)。在主窗口底部添加一個(gè)狀態(tài)欄控件,用QStatusBar實(shí)現(xiàn)。狀態(tài)欄中添加三個(gè)標(biāo)簽和一個(gè)按鈕,三個(gè)標(biāo)簽分別用于顯示當(dāng)前時(shí)間、CPU使用率、內(nèi)存使用率,這三個(gè)信息的顯示函數(shù)都與定時(shí)器QTimer綁定,隨時(shí)間自動(dòng)更新,按鈕用于觸發(fā)關(guān)機(jī)函數(shù)。在主窗口的窗體中添加tabWidget控件,設(shè)置四個(gè)tab選項(xiàng)卡tab_1、tab_2、tab_3、tab_4。tab_1選項(xiàng)卡用于顯示主機(jī)名、系統(tǒng)啟動(dòng)時(shí)間、系統(tǒng)運(yùn)行時(shí)間、系統(tǒng)版本號、CPU型號和主頻等信息,這些內(nèi)容全部用QLabel類的標(biāo)簽顯示,其中系統(tǒng)運(yùn)行時(shí)間和CPU主頻函數(shù)是槽函數(shù),都和定時(shí)器QTimer綁定,隨著時(shí)間自動(dòng)更新。tab_2選項(xiàng)卡用于顯示進(jìn)程詳細(xì)信息,進(jìn)程詳細(xì)信息包括進(jìn)程名、pid、ppid、內(nèi)存占用和優(yōu)先級,這些信息用tableWidget控件顯示,tableWidget控件設(shè)置為禁止選中、禁止修改,tableWidget的列數(shù)是固定的5列,行數(shù)動(dòng)態(tài)確定,由獲取所有進(jìn)程詳細(xì)信息的函數(shù)get_pid_info的返回值提供;這樣做的好處是,當(dāng)創(chuàng)建新進(jìn)程或者殺死進(jìn)程時(shí),tableWidget不會出現(xiàn)行數(shù)不夠或者有空行的情況,并且ProcessInfo函數(shù)(即控制顯示進(jìn)程信息的函數(shù))與QTimer綁定,隨時(shí)間定時(shí)更新。tab_3選項(xiàng)卡用于提供查詢進(jìn)程、殺死進(jìn)程、創(chuàng)建新進(jìn)程的操作面板,查詢進(jìn)程的輸入框用lineEdit控件實(shí)現(xiàn),該控件的好處是可以直接調(diào)用控件所包含的方法text獲取輸入框的內(nèi)容,便于查詢進(jìn)程信息;在lineEdit下方放置的是tableWidget控件,同樣,該控件禁止選中、禁止修改,用于顯示查詢的進(jìn)程詳細(xì)信息;tableWidget控件下方是關(guān)閉進(jìn)程的按鈕,當(dāng)點(diǎn)擊該按鈕時(shí)便會觸發(fā)killProcess函數(shù)關(guān)閉進(jìn)程;創(chuàng)建進(jìn)程的進(jìn)程名輸入框同樣也是用lineEdit控件實(shí)現(xiàn),當(dāng)點(diǎn)擊“運(yùn)行”按鈕時(shí)便會觸發(fā)CreateProcess函數(shù)。tab_4選項(xiàng)卡用于顯示CPU使用率歷史記錄曲線和內(nèi)存使用率歷史記錄曲線。(5)程序運(yùn)行結(jié)果源代碼#mainwindow.h,包含各種槽函數(shù)#ifndefMAINWINDOW_H#defineMAINWINDOW_H#include<QMainWindow>#include<QLabel>#include<QPushButton>classQTabWidget;namespaceUi{classMainWindow;}classMainWindow:publicQMainWindow{Q_OBJECTpublic:explicitMainWindow(QWidget*parent=0);~MainWindow();private:Ui::MainWindow*ui;private:QPushButton*shutButton;QLabel*NowTimeLabel;QLabel*CPUUseLabel;QLabel*MemUseLabel;QTabWidget*tabwidget;QList<float>yList;QList<float>yList1;voidinit_StatusBar();voidHostName();voidBootTime();voidOSType();voidadd_point(floatcpuRate);voidUpdateCPULine();voidadd_point_mem(floatmemRate);voidUpdateMemLine();privateslots:voidNowTime();voidCPURate();voidMemRate();voidrun_time();voidCPUInfo();voidProcessInfo();voidQueryProcess();voidPasswordToShutdown();voidKillProcess();voidCreateProcess();};#endif//MAINWINDOW_H#sys.h,獲取主機(jī)名、系統(tǒng)運(yùn)行時(shí)間、系統(tǒng)版本號#ifndefSYS#defineSYS#include<stdio.h>#include<stdlib.h>#include<string>#include<QString>char*get_hostname(){FILE*fp;charhost[8];char*hostname;hostname=(char*)malloc(7*sizeof(char));fp=fopen("/proc/sys/kernel/hostname","r");fgets(host,sizeof(host),fp);sscanf(host,"%s",hostname);fclose(fp);returnhostname;}floatget_run_time_sec(){FILE*fp;floatrunTime;chartime[32];fp=fopen("/proc/uptime","r");fgets(time,sizeof(time),fp);sscanf(time,"%f",&runTime);fclose(fp);returnrunTime;}QStringget_os_type(){QStringos;charostype[6],osrelease[8];charbuff1[16],buff2[16];FILE*fp1,*fp2;fp1=fopen("/proc/sys/kernel/ostype","r");fp2=fopen("/proc/sys/kernel/osrelease","r");fgets(buff1,sizeof(buff1),fp1);fgets(buff2,sizeof(buff2),fp2);sscanf(buff1,"%s",ostype);sscanf(buff2,"%s",osrelease);os=QString("%1%2").arg(ostype).arg(osrelease);fclose(fp1);fclose(fp2);returnos;}#endif//SYS#process.h,獲取所有進(jìn)程詳細(xì)信息#ifndefPROCESS#definePROCESS#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<dirent.h>#include<fstream>#include<iostream>#include<string>usingnamespacestd;structPROC_INFO{stringname;stringpid;stringppid;stringrss;stringpriority;}procInfo[40960];voidread_proc(PROC_INFO*pidinfo,constchar*c_pid){stringtemp,pidname;char[18];sprintf(,"/proc/%s/stat",c_pid);std::ifstreammeminfo();meminfo>>(pidinfo->pid)>>pidname>>temp>>(pidinfo->ppid)>>temp>>temp;meminfo>>temp>>temp>>temp>>temp>>temp>>temp;meminfo>>temp>>temp>>temp>>temp>>temp>>(pidinfo->priority);meminfo>>temp>>temp>>temp>>temp>>temp>>(pidinfo->rss);pidinfo->name=pidname.substr(1,pidname.find(')')-1);//remove"()"meminfo.close();}intget_pid_info(){DIR*dir;structdirent*ptr;inti=0;if(!(dir=opendir("/proc")))return0;while((ptr=readdir(dir))!=false){if(ptr->d_name[0]>='1'&&ptr->d_name[0]<='9'){read_proc(&(procInfo[i]),ptr->d_name);i++;}}closedir(dir);returni;}#endif//PROCESS#mem.h,計(jì)算內(nèi)存使用率#ifndefMEM#defineMEM#include<stdio.h>#include<stdlib.h>#include<fstream>#include<iostream>#include<string>usingnamespacestd;typedefstructMEM_USE{unsignedlongtotal;unsignedlongfree;unsignedlongbuffers;unsignedlongcached;}mem_use;voidget_mem_use_stat(mem_use*memStat){stringstr;unsignedlongmemtotal,memfree,memavailable,membuffers,memcached;std::ifstreammeminfo("/proc/meminfo");meminfo>>str>>memtotal>>str;meminfo>>str>>memfree>>str;meminfo>>str>>memavailable>>str;meminfo>>str>>membuffers>>str;meminfo>>str>>memcached>>str;(*memStat).total=memtotal;(*memStat).free=memfree;(*memStat).buffers=membuffers;(*memStat).cached=memcached;meminfo.close();}floatclacu_memRate(mem_use*memStat){floatmemRate=0.0;memRate=(float)(((*memStat).total-((*memStat).free+(*memStat).buffers+(*memStat).cached))*100.0/(*memStat).total);returnmemRate;}#endif//MEM#cpu.h,計(jì)算CPU使用率、獲取CPU型號和主頻#ifndefCPU#defineCPU#include<stdio.h>#include<stdlib.h>#include<QString>#include<QFile>#include<QTextStream>typedefstructCPU_USE{charname[16];unsignedintuser;unsignedintnice;unsignedintsystem;unsignedintidle;unsignedintiowait;unsignedintirq;unsignedintsoftirq;}cpu_use;voidget_cpu_use_stat(cpu_use*cpuStat){FILE*f;charcpu[256];f=fopen("/proc/stat","r");fgets(cpu,sizeof(cpu),f);sscanf(cpu,"%s%u%u%u%u%u%u%u",cpuStat->name,&cpuStat->user,&cpuStat->nice,&cpuStat->system,&cpuStat->idle,&cpuStat->iowait,&cpuStat->irq,&cpuStat->softirq);fclose(f);}floatcalcu_cpu_rate(cpu_use*cpuStat1,cpu_use*cpuStat2){unsignedlongtotal1,total2;floatcpuIdle=0.0;floatcpuRate=0.0;total1=(unsignedlong)(cpuStat1->user+cpuStat1->nice+cpuStat1->system+cpuStat1->idle+cpuStat1->iowait+cpuStat1->irq+cpuStat1->softirq);total2=(unsignedlong)(cpuStat2->user+cpuStat2->nice+cpuStat2->system+cpuStat2->idle+cpuStat2->iowait+cpuStat2->irq+cpuStat2->softirq);if(total1!=total2){cpuIdle=(float)((cpuStat2->idle-cpuStat1->idle)*100.0/(total2-total1));cpuRate=100.0-cpuIdle;}elsecpuRate=0.0;returncpuRate;}//getcpuinformationQStringget_processor(){inti=0;QStringprocessor;QStringstr;Q("/proc/cpuinfo");(QIODevice::ReadOnly|QIODevice::Text);QTextStreamstream(&file);stream.readLine();while(!stream.atEnd()){str=stream.readLine();if(i==3){processor=str;break;}i++;}processor=processor.mid(13,56);();returnprocessor;}QStringget_Hz0(){inti=0;QStringHz0;QStringstr;Q("/proc/cpuinfo");(QIODevice::ReadOnly|QIODevice::Text);QTextStreamstream(&file);stream.readLine();while(!stream.atEnd()){str=stream.readLine();if(i==6){Hz0=str;break;}i++;}Hz0=Hz0.mid(11,18);();returnHz0;}QStringget_Hz1(){inti=0;QStringHz1;QStringstr;Q("/proc/cpuinfo");(QIODevice::ReadOnly|QIODevice::Text);QTextStreamstream(&file);stream.readLine();while(!stream.atEnd()){str=stream.readLine();if(i==33){Hz1=str;break;}i++;}Hz1=Hz1.mid(11,18);();returnHz1;}QStringget_Hz2(){inti=0;QStringHz2;QStringstr;Q("/proc/cpuinfo");(QIODevice::ReadOnly|QIODevice::Text);QTextStreamstream(&file);stream.readLine();while(!stream.atEnd()){str=stream.readLine();if(i==60){Hz2=str;break;}i++;}Hz2=Hz2.mid(11,18);();returnHz2;}QStringget_Hz3(){inti=0;QStringHz3;QStringstr;Q("/proc/cpuinfo");(QIODevice::ReadOnly|QIODevice::Text);QTextStreamstream(&file);stream.readLine();while(!stream.atEnd()){str=stream.readLine();if(i==87){Hz3=str;break;}i++;}Hz3=Hz3.mid(11,18);();returnHz3;}#endif//CPU#mainwindow.cpp,所有功能的實(shí)現(xiàn)函數(shù)#include"mainwindow.h"#include"ui_mainwindow.h"#include<QtCore>#include<time.h>#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<QStringList>#include<QMessageBox>#include<QInputDialog>#include<QTableWidget>#include<QTableWidgetItem>#include<QProcess>#include<QPainter>#include"cpu.h"#include"mem.h"#include"sys.h"#include"process.h"MainWindow::MainWindow(QWidget*parent):QMainWindow(parent),ui(newUi::MainWindow){ui->setupUi(this);setWindowTitle("proc進(jìn)程管理器");move(0,0);resize(650,500);init_StatusBar();HostName();BootTime();OSType();QTimer*timer=newQTimer(this);connect(timer,SIGNAL(timeout()),this,SLOT(NowTime()));connect(timer,SIGNAL(timeout()),this,SLOT(CPURate()));connect(timer,SIGNAL(timeout()),this,SLOT(MemRate()));connect(timer,SIGNAL(timeout()),this,SLOT(run_time()));connect(timer,SIGNAL(timeout()),this,SLOT(CPUInfo()));connect(shutButton,SIGNAL(clicked()),this,SLOT(PasswordToShutdown()));connect(ui->queryButton,SIGNAL(clicked()),this,SLOT(QueryProcess()));connect(ui->killButton,SIGNAL(clicked()),this,SLOT(KillProcess()));connect(ui->runButton,SIGNAL(clicked()),this,SLOT(CreateProcess()));timer->start(1);QTimer*timer1=newQTimer(this);connect(timer1,SIGNAL(timeout()),this,SLOT(ProcessInfo()));timer1->start(2000);}MainWindow::~MainWindow(){deleteui;}voidMainWindow::init_StatusBar(){QStatusBar*StatBar=ui->statusBar;NowTimeLabel=newQLabel;NowTimeLabel->setMinimumSize(200,30);NowTimeLabel->setFrameShape(QFrame::WinPanel);NowTimeLabel->setFrameShadow(QFrame::Sunken);CPUUseLabel=newQLabel;CPUUseLabel->setMinimumSize(200,30);CPUUseLabel->setFrameShape(QFrame::WinPanel);CPUUseLabel->setFrameShadow(QFrame::Sunken);MemUseLabel=newQLabel;MemUseLabel->setMinimumSize(200,30);MemUseLabel->setFrameShape(QFrame::WinPanel);MemUseLabel->setFrameShadow(QFrame::Sunken);shutButton=newQPushButton;shutButton->setMinimumSize(60,30);shutButton->setText("off");StatBar->addWidget(NowTimeLabel);StatBar->addWidget(CPUUseLabel);StatBar->addWidget(MemUseLabel);StatBar->addWidget(shutButton);}voidMainWindow::NowTime(){QDateTimetime=QDateTime::currentDateTime();QStringnowTime=time.toString("yyyy-MM-ddhh:mm:ssdddd");NowTimeLabel->setText(nowTime);NowTimeLabel->setAlignment(Qt::AlignCenter);}voidMainWindow::CPURate(){cpu_usecpuStat1,cpuStat2;floatcpuRate;QStringstr;get_cpu_use_stat(&cpuStat1);sleep(1);get_cpu_use_stat(&cpuStat2);cpuRate=calcu_cpu_rate(&cpuStat1,&cpuStat2);cpuRate=((int)(cpuRate*100+0.5))/100.0;str=QString("CPU使用率:%1%2").arg(cpuRate).arg("%");CPUUseLabel->setText(str);CPUUseLabel->setAlignment(Qt::AlignCenter);add_point(cpuRate);}voidMainWindow::MemRate(){mem_useMemUse;QStringstr;floatmemRate;get_mem_use_stat(&MemUse);memRate=clacu_memRate(&MemUse);memRate=((int)(memRate*100+0.5))/100.0;str=QString("內(nèi)存使用率:%1%2").arg(memRate).arg("%");MemUseLabel->setText(str);MemUseLabel->setAlignment(Qt::AlignCenter);add_point_mem(memRate);}voidMainWindow::HostName(){char*str;QStringhostname;str=(char*)malloc(7*sizeof(char));str=get_hostname();hostname=QString(str);ui->hostlabel->setText(hostname);}voidMainWindow::run_time(){floatrunTime;runTime=get_run_time_sec();QStringrun=QString("%1%2").arg(runTime).arg("秒");ui->runtimelabel->setText(run);}voidMainWindow::BootTime(){QStringboot;time_tcur_time=0;time_tboot_time=0;structtm*ptm=NULL;time_truntime;QStringweek[7]={"星期天","星期一","星期二","星期三","星期四","星期五","星期六"};runtime=(time_t)(get_run_time_sec());time(&cur_time);boot_time=cur_time-runtime;ptm=localtime(&boot_time);boot=QString("%1-%2-%3%4:%5:%6%7").arg(ptm->tm_year+1900).arg(ptm->tm_mon+1).arg(ptm->tm_mday).arg(ptm->tm_hour).arg(ptm->tm_min).arg(ptm->tm_sec).arg(week[ptm->tm_wday]);ui->bootlabel->setText(boot);}voidMainWindow::OSType(){QStringos;os=get_os_type();ui->ostypelabel->setText(os);}voidMainWindow::PasswordToShutdown(){QStringpassWord;QStringsudo;char*command;boolOK;QByteArrayba;passWord=QInputDialog::getText(this,"輸入密碼","輸入密碼",QLineEdit::Normal,"",&OK);if(OK){sudo=QString("echo%1|sudo-Sshutdown-hnow").arg(passWord);ba=sudo.toLatin1();command=ba.data();system(command);}}voidMainWindow::CPUInfo(){QStringprocessor;QStringHz0,Hz1,Hz2,Hz3;processor=get_processor();ui->processorlabel0->setText(QString("0:%1").arg(processor));ui->processorlabel1->setText(QString("1:%1").arg(processor));ui->processorlabel2->setText(QString("2:%1").arg(processor));ui->processorlabel3->setText(QString("3:%1").arg(processor));Hz0=get_Hz0();Hz0=QString("%1%2").arg(Hz0).arg("MHz");ui->Hzlabel0->setText(Hz0);Hz1=get_Hz1();Hz1=QString("%1%2").arg(Hz1).arg("MHz");ui->Hzlabel1->setText(Hz1);Hz2=get_Hz2();Hz2=QString("%1%2").arg(Hz2).arg("MHz");ui->Hzlabel2->setText(Hz2);Hz3=get_Hz3();Hz3=QString("%1%2").arg(Hz3).arg("MHz");ui->Hzlabel3->setText(Hz3);}voidMainWindow::ProcessInfo(){intpidNum;inti;QStringListheaders;QTableWidgetItem*nameItem;QTableWidgetItem*pidItem;QTableWidgetItem*ppidItem;QTableWidgetItem*rssItem;QTableWidgetItem*priorityItem;pidNum=get_pid_info();ui->tableWidget->setColumnCount(5);ui->tableWidget->setRowCount(pidNum);headers<<"進(jìn)程名"<<"pid"<<"ppid"<<"內(nèi)存占用/KB"<<"優(yōu)先級";ui->tableWidget->setHorizontalHeaderLabels(headers);for(i=0;i<pidNum;i++){nameItem=newQTableWidgetItem(QString::fromStdString(procInfo[i].name));ui->tableWidget->setItem(i,0,nameItem);nameItem->setTextAlignment(Qt::AlignCenter);pidItem=newQTableWidgetItem(QString::fromStdString(procInfo[i].pid));ui->tableWidget->setItem(i,1,pidItem);pidItem->setTextAlignment(Qt::AlignCenter);ppidItem=newQTableWidgetItem(QString::fromStdString(procInfo[i].ppid));ui->tableWidget->setItem(i,2,ppidItem);ppidItem->setTextAlignment(Qt::AlignCenter);rssItem=newQTableWidgetItem(QString::fromStdString(procInfo[i].rss));ui->tableWidget->setItem(i,3,rssItem);rssItem->setTextAlignment(Qt::AlignCenter);priorityItem=newQTableWidgetItem(QString::fromStdString(procInfo[i].priority));ui->tableWidget->setItem(i,4,priorityItem);priorityItem->setTextAlignment(Qt::AlignCenter);}ui->tableWidget->setColumnWidth(0,121);ui->tableWidget->setColumnWidth(1,121);ui->tableWidget->setColumnWidth(2,121);ui->tableWidget->setColumnWidth(3,121);ui->tableWidget->setColumnWidth(4,121);ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);ui->tableWidget->setSelectionMode(QAbstractItemView::NoSelection);}voidMainWindow::QueryProcess(){QStringqueryitem;intpidNum,i;QStringListheaders;QTableWidgetItem*nameItem;QTableWidgetItem*pidItem;QTableWidgetItem*ppidItem;QTableWidgetItem*rssItem;QTableWidgetItem*priorityItem;QHeaderView*headerView=ui->tableWidget_2->verticalHeader();headerView->setHidden(true);//norownumberqueryitem=ui->lineEdit->text();pidNum=get_pid_info();for(i=0;i<pidNum;i++){if(queryitem==QString::fromStdString(procInfo[i].name)||queryitem==QString::fromStdString(procInfo[i].pid))break;}ui->tableWidget_2->setColumnCount(5);ui->tableWidget_2->setRowCount(1);headers<<"進(jìn)程名"<<"pid"<<"ppid"<<"內(nèi)存占用/KB"<<"優(yōu)先級";ui->tableWidget_2->setHorizontalHeaderLabels(headers);nameItem=newQTableWidgetItem(QString::fromStdString(procInfo[i].name));ui->tableWidget_2->setItem(0,0,nameItem);nameItem->setTextAlignment(Qt::AlignCenter);pidItem=newQTableWidgetItem(QString::fromStdString(procInfo[i].pid));ui->tableWidget_2->setItem(0,1,pidItem);pidItem->setTextAlignment(Qt::AlignCenter);ppidItem=newQTableWidgetItem(QString::fromStdString(procInfo[i].ppid));ui->tableWidget_2->setItem(0,2,ppidItem);ppidItem->setTextAlignment(Qt::AlignCenter);rssItem=newQTableWidgetItem(QString::fromStdString(procInfo[i].rss));ui->tableWidget_2->setItem(0,3,rssItem);rssItem->setTextAlignment(Qt::Al

溫馨提示

  • 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論