開源操作系統課程設計
實驗報告
GCC —— Matrix |
SHELL Footscript |
Ncurse —— menu |
Kernel FloppyLinux |
Driver Node & test |
Process fork & pipe |
Pthread PV operate |
Pthread Philosophy |
System Call |
SHELL simulation |
Memory simulation |
Aggregate |
|
|
|
|
|
|
|
|
|
|
|
|
評語
|
- 界面以及結構說明(程序界面菜單以及子菜單的截圖和功能說明)
1、GCC Matrix |
編譯執行打印螺旋矩陣 |
2、SHELL Footscript |
編寫腳本,實現添加和刪除用戶功能 |
3、Kernel FloppyLinux |
制作FloppyLinux |
4、Driver Node & test |
執行驅動,打印螺旋矩陣 |
5、Process fork & pipe |
實現進程的fork()和進程的pipe() |
6、Pthread PV operate |
用進程實現警察和小偷 |
7、Pthread Philosophy |
用進程實現哲學家問題 |
8、System Call |
系統調用 |
9、SHELL simulation |
模擬實現shell的命令 |
10、Memory simulation |
用首次適應算法實現內存管理 |
- 各個模塊說明
1、GCC —— Matrix
(1)實驗原理
Vim是從 vi 發展出來的一個文本編輯器。代碼補完、編譯及錯誤跳轉等方便編程的功能特別豐富,在程序員中被廣泛使用。基本上 vi/vim 共分為三種模式,分別是命令模式(Command mode),輸入模式(Insert mode)和底線命令模式(Last line mode)。
vi編輯器是所有Unix及Linux系統下標准的編輯器,他就相當於windows系統中的記事本一樣,它的強大不遜色於任何最新的文本編輯器。他是我們使用Linux系統不能缺少的工具。由於對Unix及Linux系統的任何版本,vi編輯器是完全相同的,學會它后,您將在Linux的世界里暢行無阻。vim 具有程序編輯的能力,可以以字體顏色辨別語法的正確性,方便程序設計;因為程序簡單,編輯速度相當快速。vim可以當作vi的升級版本,他可以用多種顏色的方式來顯示一些特殊的信息。vim會依據文件擴展名或者是文件內的開頭信息, 判斷該文件的內容而自動的執行該程序的語法判斷式,再以顏色來顯示程序代碼與一般信息。vim里面加入了很多額外的功能,例如支持正則表達式的搜索、多文件編輯、塊復制等等。 這對於我們在Linux上進行一些配置文件的修改工作時是很棒的功能。
本次實驗在小紅帽里寫一個簡單的C文件,編譯運行,打印螺旋矩陣。通過本次實驗,熟悉Linux中的命令,學會在終端中通過vi編譯器中,編寫簡單的程序。
(2)實驗關鍵代碼
// 輸出螺旋矩陣
void Matrix()
{
const int size = 10; // 矩陣大小
int matrix[size][size] = {0};
int row = 0;
int col = 0;
int start = 1; // 起始值
int temp = size;
for (int count = 0; count < size / 2; count++) // size階的矩陣可以畫size/2個圈
{
for (; col < temp - 1; col++) // a排賦值
matrix[row][col] = start++;
for (; row < temp - 1; row++) // b排賦值
matrix[row][col] = start++;
for (col = temp - 1; col > count; col--) // c排賦值
matrix[row][col] = start++;
for (row = temp - 1; row > count; row--) // d排賦值
matrix[row][col] = start++;
// 進入下一圈
temp--;
row++;
start -= 1; // 這里-1是因為在換圈的時候會多加1
}
if (0 != size % 2) // 如果size為奇數則最后會有一個數遍歷不到,這里補上
matrix[row][col+1] = start + 1;
// 輸出數組
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
printf(" %d",matrix[i][j]);
}
printf("\n");
}
}
(3)程序流程圖(手寫)
(4)實驗結果及總結
通過本次實驗,加深了我對Linux操作系統的認識,加深了我對Linux的指令的認識。通過這次實驗,我熟悉了 linux 下 c 語言程序的編寫,掌握了 vi 的一些常用操作,學會了使用 gcc 命令和 makefile 文件兩種方法編譯程序。同時也使我熟悉了 linux 里常用命令的使用,還有,學會了掛載 U盤的方法,可以很方便的往 linux 里傳送文件。
2、SHELL Footscript
(1)實驗原理
Shell腳本(英語:Shell script)是一種電腦程序與文本文件,內容由一連串的shell命令組成,經由Unix Shell直譯其內容后運作。被當成是一種腳本語言來設計,其運作方式與直譯語言相當,由Unix shell扮演命令行解釋器的角色,在讀取shell script之后,依序運行其中的shell命令,之后輸出結果。利用Shell script可以進行系統管理,文件操作等。
在Linux中默認安裝就帶了shell解釋器。
(2)實驗關鍵代碼
#!/bin/sh
i=1
while [ $i -le 4 ]
do
GROUPNAME=class${i}
groupadd $GROUPNAME
i=$(($i+1))
done
i=0
k=0
while [ $i -lt 120 ]
do
if [ $(($i%30)) -eq 0 ]
then
k=$(($k+1))
fi
j=$((($i)%30))
j=$(($j+1))
if [ $j -le 9 ]
then
USERNAME=class${k}stu0${j}
else
USERNAME=class${k}stu${j}#
fi
GROUPNAME=class${k}
useradd $USERNAME
chown -R $USERNAME /home/$USERNAME
chgrp -R $GROUPNAME /home/$USERNAME
i=$(($i+1))
Done
(3)程序流程圖(手寫)
(4)實驗結果及總結
通過本次實驗,學會了腳本程序的編寫,學會了利用腳本實現簡單的功能。這是課程設計的第二次實驗,通過這幾次實驗,體會到了樂趣。
3、Kernel FloppyLinux
(1)實驗原理
在虛擬機中虛擬一張1.44M的軟盤,就可以制作自己的Linux操作系統了,通過本實驗可以對Linux的開機啟動過程,根文件系統的制作,內核的編譯有更深的理解。創建一個啟動盤首先必須創建根文件系統,由於軟盤容量有限,因此常采用壓縮的根文件系統。
一個啟動盤實際上是一個完整系統的縮影,它能夠執行一個完整系統的大部分功能。引導系統就是在操作系統內核運行之前運行的一段小程序,能夠初始化硬件設備、建立內存空間的映射圖,並且為最終調用操作系統內核准備好正確的環境;而內核是一個操作系統的核心,負責管理系統的進程、存儲、設備和文件等功能,決定着系統的性能和穩定性.
(2)實驗關鍵代碼
timeout 0
default 10
title wangjian’FloppyLinux
root (fd0)
kernel /boot/bzImage
initrd /initrd.img.gz
(3)程序流程圖(手寫)
(4)實驗結果及總結
通過本次實驗,我了解了 linux 系統的啟動過程,進一步熟悉了 linux 內核編譯過程。學會
了 floppylinux 的制作方法,做成之后非常有成就感。我認為本實驗並不難,考驗的是細心。實
驗步驟很多,每個步驟出現錯誤,都有可能導致實驗失敗。所以要力求每個步驟准確無誤,特別
是建立啟動配置文件的時候,要仔細核對每一個單詞,特別注意空格。前面幾遍沒有成功沒有成功,原因就出在這里。總之,面對一個步驟復雜的事情,要細心。
4、Driver Node & test
(1)實驗原理
驅動程序,英文名為“Device Driver”,全稱為“設備驅動程序”,它是一種特殊的程序。首先其作用是將硬件本身的功能告訴操作系統,接下來的主要功能就是完成硬件設備電子信號與操作系統及軟件的高級編程語言之間的互相翻譯。
Linux內核使用驅動時候,需要先初始化,包括建立設備文件,分配內存地址空間等,退出的時候要釋放資源,刪除設備文件,釋放內存地址空間等。所以在linux驅動中需要提供兩個函數來分別處理驅動初始化和退出的工作,這兩個函數分別用module_init和module_exit宏來指定,linux驅動一般都需要指定這兩個函數,所以linux驅動有一個C文件,文件中包含處理驅動初始化和退出的函數,以及指定這兩個函數的module_init和module_exit宏.
在Linux操作系統下有三類主要的設備文件類型,一是字符設備,二是塊設備,三是網絡設備。字符設備和塊設備的主要區別是:在對字符設備發出讀/寫請求時,實際的硬件I/O一般就緊接着發生了,塊設備則不然,它利用一塊系統內存作緩沖區,當用戶進程對設備請求能滿足用戶的要求,就返回請求的數據,如果不能,就調用請求函數來進行實際的I/O操作。塊設備是主要針對磁盤等慢速設備設計的,以免耗費過多的CPU時間來等待。
本次實驗主要是針對字符設備來進行操作。主要操作步驟如下:
- 修改Makefile文件內容。修改內核源碼路徑:/usr/src/linux-2.4,修改gcc前綴,設置為空。
- 執行make操作,生成evan.o、test_demo等。
- insmod evan.o。可以通過lsmod查看是否成功。
- 建立驅動結點。執行mknod /dev/evan c 99 0。
- 最后執行。/test_demo。
(2)實驗關鍵代碼
static void do_write()//do_wiite()函數,在這里面生成螺旋。
{
int i;
int start=65;int row=0;int col=0;
int m=M;int n=N;int cnt;int flag=1;
if(M>=N)
{cnt=N;}
else
{cnt=M+1;}
for(i=0;i<cnt/2;i++)
{
for(;col<n-1;col++)
{drv_buf[row*N+col]=start;start++;}
if(row>=m-1)
{flag=0;}
for(;row<m-1;row++)
{drv_buf[row*N+col]=start;start++;}
for(col=n-1;col>i;col--)
{
drv_buf[row*N+col]=start;
start++;
if(flag==0)
{break;}
}
for(row=m-1;row>i;row--)
{drv_buf[row*N+col]=start;start++;}
m--;n--;row++;start--;
}
start++;
if(N%2!=0)
{
int z=M-2*row;for(i=0;i<z;i++)
{
drv_buf[row*N+col+1]=start;
start++;row++;
}
}
}
static ssize_t evan_write(struct file *filp, char *buffer, size_t count)// evan_write()函數
{
if (count>MAX_BUF_LEN) count=MAX_BUF_LEN;
copy_from_user(drv_buf,buffer,count);
WRI_LENGTH=count;
M=buffer[0];
N=buffer[1];
printk("user write data to drivers!\n");
do_write();
return count;
}
(3)程序流程圖(手寫)
(4)實驗結果及總結
通過本次實驗,加深了我對驅動程序的認識,Linux系統將每一個驅動都映射成一個文件。這些文件稱為設備文件或驅動文件,都存在/dev目錄中。這樣,在應用程序看來,硬件設備只是一個設備文件,應用程序可以像操作普通文件一樣對硬件設備進行操作,從而大大方便了對設備的處理。
通過在應用程序中生成數組,輸入行數與列數,並將其傳到驅動程序中,進而生成螺旋矩陣函數,使我對驅動程序有了初步的認識。
5、Process fork & pipe
(1)實驗原理
每個進程各自有不同的用戶地址空間,任 何一個進程的全局變量在另一個進程中都看不到,所以進程之間要交換數據必須通過內核,在內核中開辟一塊緩沖 區,進程1把數據從用戶空間拷到內核緩沖區,進程2再從內核緩沖區把數據讀走,內核提供的這種機制稱為進程間通信(IPC,InterProcess Communication)。
管道是一種最基本的IPC機制,由pipe函數創建。調用pipe函數時在內核中開辟一塊緩沖區(稱為管道)用於通信,它有一個讀端一個寫端,然后通過filedes參數傳出給用戶程序兩個文件描述符。所以管道在用戶程序看起來就像一個打開的文件,通過read(filedes[0]);或者write(filedes[1]);向這個文件讀寫數據其實是在讀寫內核緩沖區。pipe函數調用成功返回0,調用失敗返回-1。
由fork創建的新進程被稱為子進程(child process)。該函數被調用一次,但返回兩次。兩次返回的區別是子進程的返回值是0,而父進程的返回值則是新進程(子進程)的進程 id。將子進程id返回給父進程的理由是:因為一個進程的子進程可以多於一個,沒有一個函數使一個進程可以獲得其所有子進程的進程id。對子進程來說,之所以fork返回0給它,是因為它隨時可以調用getpid()來獲取自己的pid;也可以調用getppid()來獲取父進程的id。
(2)實驗關鍵代碼
(3)程序流程圖(手寫)
(4)實驗結果及總結
通過本次實驗,我對操作系統的進程有了更深入的了解,為接下來的進程實驗打下基礎。這次實驗老師給了大部分的代碼,實現起來相對簡單。同時,加深了我對操作系統理論課上學到的知識的理解。
6、Pthread PV operate
(1)實驗原理
警察與小偷一個十分經典的多線程並發協作的模式,在深刻理解生產者-消費者問題的基礎上,警察與小偷問題能夠讓我們對並發編程的理解加深。所謂生產者-消費者問題,實際上主要是包含了兩類進程,一種是生產者進程用於生產數據,另一種是消費者進程用於消費數據,為了解耦生產者和消費者的關系,通常會采用共享的數據區域,就像是一個倉庫,生產者生產數據之后直接放置在共享數據區中,並不需要關心消費者的行為;而消費者只需要從共享數據區中去獲取數據,就不再需要關心生產者的行為。而警察與小偷問題,同樣包含兩類進程,警察進程和小偷進程,與生產者消費者問題不同的是,小偷可以在警察前面,警察也可以在小偷前面,但是彼此之間的距離不能超過3米。
(2)實驗關鍵代碼
void put(struct prodcons * b, int data)
{
pthread_mutex_lock(&b->lock);
while (b->writepos - b->readpos >=2) {
pthread_cond_wait(&b->notfull, &b->lock);
}
b->buffer[b->writepos] = data;
b->writepos++;
initP(b->writepos,b->readpos);
pthread_cond_signal(&b->notempty);
pthread_mutex_unlock(&b->lock);
}
int get(struct prodcons * b)
{
int data,i;
pthread_mutex_lock(&b->lock);
while (b->writepos - b->readpos <= -4) {
pthread_cond_wait(&b->notempty, &b->lock);
}
data = b->buffer[b->readpos];
b->readpos++;
initP(b->writepos,b->readpos);
pthread_cond_signal(&b->notfull);
pthread_mutex_unlock(&b->lock);
return data;
}
(3)程序流程圖(手寫)
(4)實驗結果及總結
這個程序我結合着老師給生產者消費者程序框架,重新整理思路,認識到警察與小偷問題同樣包含兩類進程,警察進程和小偷進程,與生產者消費者問題不同的是,小偷可以在警察前面,警察也可以在小偷前面,但是彼此之間的距離不能超過3米。而生產者與消費者問題,強制要求了生產者必須在消費者的前面,並且二者的距離不能超過緩沖池的長度。
思路明確后,編程就變得簡單了。同時實驗要求使用ncurses,將文字式的輸出編程生動的動畫,令人印象深刻。
7、Pthread Philosop hy
(1)實驗原理
哲學家進餐問題描述:一張圓桌上坐着5名哲學家,每兩個哲學家之間的桌上擺一根筷子,桌子的中間是99根面條。哲學家們傾注畢生精力用於思考和進餐,哲學家在思考時,並不影響他人。只有當哲學家飢餓的時候,才試圖拿起左、 右兩根筷子(一根一根地拿起)。如果筷子已在他人手上,則需等待。飢餓的哲學家只有同時拿到了兩根筷子才可以開始進餐,當進餐完畢后,放下筷子繼續思考。
實驗思路是在界面上畫一張圓桌,五個哲學家圍桌而坐,每兩個哲學家中間有一個筷子,圓桌中間有一個數字代表剩余面條的數目。
(2)實驗關鍵代碼
void init(int i,int noddle)
{
clear();char a,b;
if(noddle>=10)
{a=noddle/10+'0';b=noddle%10+'0';mvaddch(4,9,a);mvaddch(4,10,b);}
else
{a=noddle+'0';mvaddch(4,9,a);}
mvaddch(0,10,'B');mvaddch(4,0,'A');mvaddch(4,20,'C');mvaddch(8,15,'D');mvaddch(8,5,'E');
mvaddstr(2,3,"--------------");mvaddstr(6,3,"--------------");
mvaddch(2,3,'|');mvaddch(3,3,'|');mvaddch(4,3,'|');mvaddch(5,3,'|');
mvaddch(3,17,'|');mvaddch(4,17,'|');mvaddch(5,17,'|');mvaddch(6,17,'|');
if(i==1)
{mvaddch(5,2,'-');mvaddch(3,2,'-');mvaddch(4,15,'-');mvaddch(5,15,'|');mvaddch(5,5,'|');}
else if(i==2)
{mvaddch(4,4,'-');mvaddch(1,12,'|');mvaddch(1,8,'|');mvaddch(5,15,'|');mvaddch(5,5,'|');}
else if(i==3)
{mvaddch(4,4,'-');mvaddch(3,10,'|');mvaddch(5,18,'-');mvaddch(3,18,'-');mvaddch(5,5,'|');}
else if(i==4)
{mvaddch(4,4,'-');mvaddch(3,10,'|');mvaddch(4,15,'-');mvaddch(7,17,'|');mvaddch(7,13,'|');}
else
{mvaddch(7,7,'|');mvaddch(3,10,'|');mvaddch(4,15,'-');mvaddch(5,15,'|');mvaddch(7,3,'|');}
refresh();
}
void initfh(int noddle)
{
clear();char a,b;
if(noddle>=10)
{a=noddle/10+'0';b=noddle%10+'0';mvaddch(4,9,a);mvaddch(4,10,b);}
else
{a=noddle+'0';mvaddch(4,9,a);}
mvaddch(0,10,'B');mvaddch(4,0,'A');mvaddch(4,20,'C');mvaddch(8,15,'D');mvaddch(8,5,'E');
mvaddstr(2,3,"--------------");mvaddstr(6,3,"--------------");
mvaddch(2,3,'|');mvaddch(3,3,'|');mvaddch(4,3,'|');mvaddch(5,3,'|');
mvaddch(3,17,'|');mvaddch(4,17,'|');mvaddch(5,17,'|');mvaddch(6,17,'|');
mvaddch(4,4,'-');mvaddch(3,10,'|');mvaddch(4,15,'-');mvaddch(5,15,'|');mvaddch(5,5,'|');
refresh();
}
(3)程序流程圖(手寫)
(4)實驗結果及總結
第一次用ncurses畫這么負責的圖,使我對ncurses的功能有了更深刻的認識,簡單的ncurses卻能實現如此強大的功能。這次實驗花費了很多時間花費了好多時間用來畫圖,使我對ncurses的使用有了更深刻的認識。
在完成這個實驗的過程中,我遇到了許多的困難,但是好在通過同學的幫助,我慢慢的一一解決了。總的來說,哲學家算法是一個經典的課題,此次的實踐的帶給我的收獲絕不止實現一個實驗這么簡單。
8、System Call
(1)實驗原理
系統調用是內核提供的、功能十分強大的一系列函數。它們在內核中實現,然后通過一定的方式呈現給用戶,是用戶程序與內核交互的一個接口。如果沒有系統調用,則不可能編寫出十分強大的用戶程序,因為失去了內核的支持。由此可見系統調用的地位舉足輕重。
應用程序執行系統調用之后,將進行模式轉換,從用戶態切換到內核態,之后在內核空間調用內核函數。執行完畢后又從內核態切換回用戶態,並在原來的應用程序斷點繼續執行下去。
本次實驗通過在添加打印螺旋矩陣的系統調用,進而證明這個進程進入過內核態。
(2)實驗關鍵代碼
asmlinkage int sys_print_info(int m,int n)
{
printk(KERN_EMERG "my id is 1609030225\n");
printk(KERN_EMERG "my name is wangjian\n");
char a[100][100];
int x, y;
int total = 0;
int cnt = 0;
x = 0, y = 0;
a[x][y] = 0;
while(total < m*n){
while(y+1<n&&!a[x][y+1]){
a[x][++y] = ++cnt;
++total;
}
while(x+1<m&&!a[x+1][y]){
a[++x][y] = ++cnt;
++total;
}
while(y-1>=0&&!a[x][y-1]){
a[x][--y] = ++cnt;
++total;
}
while(x-1>=0&&!a[x-1][y]){
a[--x][y] = ++cnt;
++total;
}
}
for(x = 0;x < m;x++){
for(y = 0;y < n;y++){
printk(KERN_EMERG " %d",a[x][y]);
}
printk(KERN_EMERG "\n");
}
return 0;
}
(3)程序流程圖(手寫)
(4)實驗結果及總結
本次實驗通過添加一個簡單的系統調用,打印出自己的學號和姓名,並且實現了輸入行數和列數打印螺旋矩陣。
需要注意本次系統調用與前一次的驅動打印螺旋矩陣的不同,雖然兩個實驗都需要進行終端和系統調用,但是本次系統調用實驗需要重新編譯內核,而驅動實驗只是建立驅動節點而已。
系統調用是一層用戶進入內核的接口,通過實驗加深了操作系統理論課上學習到知識,系統調用與普通的函數調用非常相似,區別僅僅在於,系統調用由操作系統核心提供,運行於核心態;而普通的函數調用由函數庫或用戶自己提供,運行於用戶態。通過實驗,我認識到了內核的重要性,在以后的學習中,我會更加努力。
9、SHELL simulation
(1)實驗原理
Shell 是一個用 C 語言編寫的程序,它是用戶使用 Linux 的橋梁。Shell 既是一種命令語言,又是一種程序設計語言。
Shell 是指一種應用程序,這個應用程序提供了一個界面,用戶通過這個界面訪問操作系統內核的服務。
Shell 腳本(shell script),是一種為 shell 編寫的腳本程序。
(2)實驗關鍵代碼
#!/bin/sh
who(){
echo "wangjian 1609030225"
}
bye(){
echo "before exit"
exit
echo "after exit"
}
pwd(){
workdir=$(cd $(dirname $0) :pwd)
echo ”$workdir"
}
down( ){
shutdown -r now
}
wc -1 < infile
exec 0< infile
while read line
do
echo "Line #$count: $line"
count=$[ $count + 1 ]
done
who >> outfile
pwd >> outfile
bye >> outfile
(3)程序流程圖(手寫)
(4)實驗結果及總結
通過本次shell腳本編程實驗,學會了了利用shell實現部分系統的內部命令(bye、down、who、pwd等)和外部命令,並且實現了輸入輸出重定向功能。
本次實驗的感悟到shell命令很神奇,通過一系列命令就可以搞定文件的操作,在這些命令之后再加一些字母,便可以做一些更加詳細的操作。
10、Memory simulation
(1)實驗原理
通過首次適應算法,然后在ncurses圖形界面下顯示手動顯示內存申請和內存釋放功能。
首次適應算法從空閑分區表的第一個表目起查找該表,把最先能夠滿足要求的空閑區分配給作業,這種方法目的在於減少查找時間。為適應這種算法,空閑分區表(空閑區鏈)中的空閑分區要按地址由低到高進行排序。該算法優先使用低址部分空閑區,在低址空間造成許多小的空閑區,在高地址空間保留大的空閑區。
思路是利用數據結構中的二叉樹,內存申請時,便插入左右孩子,左孩子為作業,右孩子為空閑區。申請內存時便在界面上打印“-”,表示該段內存被占用,同時在中間打印出內存大小。釋放內存時,在界面上打印“ ”,便是該段內存被釋放。
(2)實驗關鍵代碼
void Insert_PreOrder(pBiTree p,int length,int homework)//內存申請函數
{
initscr();
crmode();
noecho();
if(p != NULL)
{
if((p->state==0)&&(length<p->length)&&(!p->lchild)&&(!p->rchild)&&temp==0)
{
pBiTree x1 =new BiTNode;//進行插入,動態申請兩個空間 x1,x2
pBiTree x2 =new BiTNode;
x1->homework=homework;//x1為作業
x2->homework=NULL;//x2為剩余的空閑區
x1->address=p->address;//把原空閑區的首地址給作業的首地址
x1->state=1;//作業的狀態改為1
x1->length=length;//作業的長度為傳入的長度
int i;
for(i=x1->address; i<x1->address+x1->length; i++)
{
mvaddch(13,i,'-');
}
char c,b;
int j=x1->length;
if(i>=10)
{
c=j/10+'0';
b=j%10+'0';
mvaddch(13,x1->address+x1->length/2,c);
mvaddch(13,1+x1->address+x1->length/2,b);
}
else
{
c=j+'0';
mvaddch(13,x1->address+x1->length/2,c);
}
mvaddch(12,i,'|');mvaddch(13,i,'|');mvaddch(14,i,'|');
x2->address=x1->address+length;//新空閑親地址與x1長度之和
x2->length=p->length-x1->length;
p->lchild=x1;
p->rchild=x2;
x2->state=0;
x1->lchild=NULL;
x1->rchild=NULL;
x2->rchild=NULL;
x2->lchild=NULL;
temp=1;
}
else
{
Insert_PreOrder(p->lchild,length,homework); //遍歷左子樹
Insert_PreOrder(p->rchild,length,homework); //遍歷右子樹
}
}
refresh();
endwin();
}
void Delect_PreOrder(pBiTree p,int homework) //內存釋放函數,遍歷修改,將狀態修改為0。
{
initscr();
crmode();
noecho();
if(p != NULL)
{
if(p->homework==homework)//當查詢到作業名相同的作業。進行修改
{
p->homework=NULL;//將作業名修改為空
p->state=0;
int i;
for(i=p->address; i<p->address+p->length; i++)
{
mvaddch(13,i,' ');
}
}
Delect_PreOrder(p->lchild,homework); //遍歷左子樹
Delect_PreOrder(p->rchild,homework); //遍歷右子樹
}
refresh();
endwin();
}
(3)程序流程圖(手寫)
(4)實驗結果及總結
通過這次實驗,學會了通過首次適應算法,來進行申請內存和釋放內存。實驗中在使用ncurses打印圖形界面時,遇到了bug(執行程序沒有任何反應),通過上網查資料,發現需要在每次進行操作(內存申請和內存釋放)時,都需要對界面進行刷新,所以我在內存申請函數和內存釋放函數中添加
ncurses初始化函數並進行刷新,問題得到了解決。
- 課程總結以及建議
通過本學期的開源操作系統課程設計,加深了理論課操作系統學到的知識。通過這十一次的實驗,從最開始的Linux基礎的指令,到后面的進程管理、存儲器管理等等。其中的系統調用和驅動對我影響很大,最開始我的疑問是為什么系統調用實驗需要重新編內核,而驅動實驗不需要重新編譯內核,只需要通過insmod添加節點。
非常感謝老師這一個學期的辛苦指導。實驗過程中遇到了許多問題,通過老師和同學們的幫忙最終都一一克服了。