




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
董永文07057409-操作系統(tǒng)課程設(shè)計(jì)實(shí)驗(yàn)報(bào)告姓名:董永文專業(yè):軟件工程班級:07052714學(xué)號:070574092010年7月
任務(wù)一、基于線程的多任務(wù)程序設(shè)計(jì)一、實(shí)驗(yàn)?zāi)康谋緦?shí)驗(yàn)旨在促進(jìn)對于線程控制、調(diào)度算法和消息通信機(jī)制的理解。這里的多線程并不使用任何的操作系統(tǒng)提供的線程系統(tǒng)調(diào)用,而是依靠自己的線程相關(guān)函數(shù)完成上述目標(biāo),線程的調(diào)度依靠的是改造后的時鐘中斷處理程序來實(shí)現(xiàn)的。二、實(shí)驗(yàn)要求本實(shí)驗(yàn)要求實(shí)現(xiàn)如下要求:1.設(shè)計(jì)實(shí)現(xiàn)基于線程多任務(wù)程序2.完成生產(chǎn)者消費(fèi)者程序設(shè)計(jì)3.實(shí)現(xiàn)線程間的消息通信程序三、已經(jīng)實(shí)現(xiàn)的功能1.設(shè)計(jì)實(shí)現(xiàn)基于線程多任務(wù)程序2.完成生產(chǎn)者消費(fèi)者程序設(shè)計(jì)3.實(shí)現(xiàn)線程間的消息通信程序四、未能實(shí)現(xiàn)的功能五、程序設(shè)計(jì)思路與代碼分析任務(wù)一主要需要實(shí)現(xiàn)的功能可以分為五部分:(一)線程的創(chuàng)建和撤消(二)調(diào)度程序的實(shí)現(xiàn)(三)進(jìn)程的阻塞和喚醒(四)利用消息緩沖隊(duì)列的線程間通信(五)生產(chǎn)者消費(fèi)者問題的實(shí)現(xiàn)因此本程序可以以上功能實(shí)現(xiàn)先后順序?yàn)樵O(shè)計(jì)思路,進(jìn)行代碼編寫。(一)線程的創(chuàng)建和撤消1、TCB的設(shè)計(jì):TCB是實(shí)現(xiàn)以上功能的必要前提,所以要考慮周全
#defineFINISHED
0
#defineRUNNING
1
#defineREADY
2
#defineBLOCKED
3#defineNTCB
100structTCB
{
unsignedchar
*stack;
/*堆棧的起始地址*/
unsigned
ss;
/*堆棧段址*/
unsigned
sp;
/*堆棧指針*/
char
state;
/*線程的外部標(biāo)識符*/
char
name[10];/*NTCB是系統(tǒng)允許的最多任務(wù)個數(shù)*/structbuffer *mq;/*消息隊(duì)列隊(duì)首指針,初值為NULL*/
structsemaphoremutex;
/*消息隊(duì)列的互拆信號量,初值為{1,NULL}*/
structsemaphoresm;
/*消息隊(duì)列的計(jì)數(shù)信號量,初值為{0,NULL}*/intreaderNum;/*當(dāng)線程作為讀線程時所讀線程的線程內(nèi)部標(biāo)識符*/
}tcb[NTCB];2、創(chuàng)建線程:線程創(chuàng)建的一般步驟
1.為新線程分配一個線程控制塊,TCB數(shù)組的下標(biāo)即為該線程的內(nèi)部標(biāo)識符。
2.為新線程分配私有堆??臻g。
3.初始化新線程的私有堆棧,即按CPU調(diào)度時現(xiàn)場信息的保存格式布置堆棧。
4.初始化線程控制塊。
5.其它工作。如按優(yōu)先級進(jìn)行CPU調(diào)度,則需在TCB中加上優(yōu)先權(quán)信息。
6.返回新線程的內(nèi)部標(biāo)識符。為新線程分配私有堆??臻gintcreate(char*name,codeptrcode,unsignedstacklen,unsignedprio){ inti; structint_regs*ir; for(i=1;i<NTCB;i++) if(tcb[i].state==FINISHED) break; if(i==NTCB)return-1; strcpy(tcb[i].name,name); tcb[i].stack=(unsignedchar*)malloc(stacklen); tcb[i].ss =FP_SEG(tcb[i].stack); tcb[i].sp =FP_OFF(tcb[i].stack+stacklen); tcb[i].state=READY; tcb[i].prio=prio; *((unsigned*)(tcb[i].sp-2))=FP_SEG(over); *((unsigned*)(tcb[i].sp-4))=FP_OFF(over); tcb[i].sp-=(sizeof(structint_regs)+4); ir=(structint_regs*)tcb[i].sp; ir->ds=tcb[i].ss; ir->es=tcb[i].ss; ir->ip=FP_OFF(code); ir->cs=FP_SEG(code); ir->flags=0x200; returni;}3、撤消線程1.釋放線程的私有堆??臻g。
2.重新進(jìn)行CPU調(diào)度。
voidover()
{
if(tcb[current].state==RUNNING)
{
free(tcb[current].stack);
tcb[current].state=FINISHED;
}
SWITCH();
/*重新進(jìn)行CPU調(diào)度*/
}(二)調(diào)度程序的實(shí)現(xiàn)利用時鐘中斷來進(jìn)行CPU調(diào)度,設(shè)計(jì)中要注意:新中斷處理程序不能太長,否則系統(tǒng)效率將大大降低甚至使系統(tǒng)無法正常工作;在新的時鐘中斷處理程序里必須調(diào)用系統(tǒng)原來的INT08H,否則將影響磁盤馬達(dá)和系統(tǒng)的計(jì)時。voidinterruptSWITCH(){ disable();tcb[current].ss=_SS;tcb[current].sp=_SP;if(tcb[current].state==RUNNING) tcb[current].state=READY;current=find();_SS=tcb[current].ss;_SP=tcb[current].sp;tcb[current].state=RUNNING;enable();}voidinterruptnew_int8()
{
/*調(diào)用原來的中斷處理程序*/
(*old_int8)();
timecount++;
/*優(yōu)先級加1*/
tcb[current].prio++;
if(timecount>=TLE)
{
disable();
tcb[current].ss=_SS;
tcb[current].sp=_SP;
if(tcb[current].state==RUNNING)
tcb[current].state=READY;
current=find();
_SS=tcb[current].ss;
_SP=tcb[current].sp;
tcb[current].state=RUNNING;
timecount=0;
enable();
}
}(三)進(jìn)程的阻塞和喚醒線程阻塞過程:將線程的狀態(tài)改成阻塞態(tài),將線程插入指定的阻塞隊(duì)列末尾,并重新進(jìn)行CPU調(diào)度。
線程喚醒過程:把阻塞隊(duì)列頭上的第一個線程的TCB取下來,并將其狀態(tài)改為就緒態(tài),并重新進(jìn)行CPU調(diào)度。structblock_entry
{unsigned
thread;
structblock_entry*next;};structsemaphore
{
int
value;
structblock_entry*L;};
voidInitSemaphore(structsemaphore*ps)
{
ps->value=SIGNAL_VALUE;
ps->L
=NULL;}voidblock(structsemaphore*ps)
{
structblock_entry*pbe;
tcb[current].state=BLOCKED;
pbe=(structblock_entry*)malloc(sizeof(structblock_entry));
pbe->thread=current;
pbe->next
=ps->L;
ps->L
=pbe;
printf("Thread%disblocked!\n",current);
SWITCH();
}voidwakeup(structsemaphore*ps)
{
structblock_entry*pbe;
pbe=ps->L;
if(!pbe)
{
printf("Blockqueueisempty!\n");
SWITCH();
}
tcb[pbe->thread].state=READY;
ps->L=pbe->next;
free(pbe);
printf("Thread%dhasbeenwakedup!\n",pbe->thread);
SWITCH();
}voidwait(structsemaphore*ps)
{
disable();
ps->value--;
if(ps->value<0)
block(ps);
enable();}voidsignal(structsemaphore*ps)
{
disable();
ps->value++;
if(ps->value<=0)
wakeup(ps);
enable();}(四)利用消息緩沖隊(duì)列的線程間通信假設(shè)剛開始時系統(tǒng)中有NBUF個消息緩沖區(qū),它們排成一個消息隊(duì)列freebuf,為實(shí)現(xiàn)對該隊(duì)列操作的互斥,設(shè)置信號量mutexb(初值為{1,NULL})。
發(fā)送消息時,發(fā)送者必須提供接收者的標(biāo)識符、消息的長度及消息正文的起始地址等信息。
接收消息時,接收者必須指出發(fā)送者的標(biāo)識符、接收區(qū)的起始地址等信息。/*從空閑消息緩沖隊(duì)列頭上取下一緩沖區(qū),返回指向該緩沖區(qū)的指針*/
structbuffer*getbuf()
{
structbuffer*buff;
buff=freebuf;
freebuf=freebuf->next;
returnbuff;
}/*將buff所指向的消息緩沖區(qū)加到空閑消息緩沖隊(duì)列中去*/
voiddropbuf(structbuffer*buff)
{
buff->next=freebuf;
freebuf=buff;
}/*將buff所指的緩沖區(qū)插到*mq所指的緩沖隊(duì)列末尾*/
voidinsert(structbuffer**mq,structbuffer*buff)
{
structbuffer*temp;
if(buff==NULL)return;
buff->next=NULL;
if(*mq==NULL)
*mq=buff;
else
{
temp=*mq;
while(temp->next)
temp=temp->next;
temp->next=buff;
}
}/*從*mq所指的緩沖隊(duì)列中移除buff所指的緩沖區(qū)*/
voiddelet(structbuffer**mq,structbuffer*buff)
{
structbuffer*temp;
if(!*mq)return;
if(!buff)return;
if(*mq==buff)
{
*mq=buff->next;
return;
}
for(temp=*mq;temp->next!=buff;temp=temp->next);
temp->next=buff->next;
}/*將地址a開始的size個字節(jié)內(nèi)容發(fā)送給receiver線程*/
voidsend(char*receiver,char*a,intsize)
{
structbuffer*buff;
inti,id=-1;
disable();
for(i=0;i<NTCB;i++)
if(!strcmp(receiver,tcb[i].name))
{
id=i;
break;
}
if(-1==id)
{
printf("Error:Receivernotexsist!\n");
enable();
return;
}
wait(&sfb);
wait(&mutexfb);
buff=getbuf();
signal(&mutexfb);
buff->sender=current;
buff->size=size;
buff->next=NULL;
for(i=0;i<size;i++,a++)
buff->text[i]=*a;
wait(&tcb[id].mutex);
insert(&(tcb[id].mq),buff);
signal(&tcb[id].mutex);
signal(&tcb[id].sm);
enable();
}/*接收sender發(fā)送來的消息到a所指的緩沖區(qū)中*/
voidrecv(char*sender,char*a)
{
structbuffer*buff;
inti,id=-1;
buff=tcb[current].mq;
disable();
while(buff)
{
/*printf("%d\n",buff->sender);*/
if(!strcmp(sender,tcb[buff->sender].name))
{
id=buff->sender;
break;
}
buff=buff->next;
}
if(-1==id)
{
printf("Error:Sendernotexsist!\n");
enable();
return;
}
for(i=0;i<buff->size;i++,a++)
*a=buff->text[i];
wait(&tcb[current].mutex);
delet(&(tcb[current].mq),buff);
signal(&tcb[current].mutex);
wait(&tcb[current].sm);
signal(&sfb);
wait(&mutexfb);
dropbuf(buff);
signal(&mutexfb);
enable();
}(五)生產(chǎn)者消費(fèi)者問題的實(shí)現(xiàn)voidproduce(){ inti; for(i=0;i<10;i++){ disable(); production=rand()%(Y-X+1)+X; production*=production; fprintf(fp,"current=%dprodece1produce_cnt=%dconsume_cnt=%dproduction=%d\n",current,produce_cnt,consume_cnt,production); enable(); wait(empty); wait(mutex); produce_cnt++; disable(); fprintf(fp,"current=%dprodece2produce_cnt=%dconsume_cnt=%dproduction=%d\n",current,produce_cnt,consume_cnt,production); enable(); signal(mutex); signal(full); }}voidconsume(){ inti; for(i=0;i<10;i++){ disable(); fprintf(fp,"current=%dconsume1produce_cnt=%dconsume_cnt=%dproduction=%d\n",current,produce_cnt,consume_cnt,production); enable(); wait(full); wait(mutex); consume_cnt++; disable(); fprintf(fp,"current=%dconsume2produce_cnt=%dconsume_cnt=%dproduction=%d\n",current,produce_cnt,consume_cnt,production); enable(); signal(mutex); signal(empty); }}六、實(shí)驗(yàn)結(jié)論1、線程間通信的結(jié)果如下:Thread1:Sendthread2:thread1tothread2-1!Thread2:Sendthread3:thread2tothread3-1!Thread3:Sendthread1:thread3tothread1-1!Thread1:Sendthread2:thread1tothread2-2!Thread2:Sendthread3:thread2tothread3-2!Thread3:Sendthread1:thread3tothread1-2!Thread1:Sendthread2:thread1tothread2-3!Thread2:Sendthread3:thread2tothread3-3!Thread3:Sendthread1:thread3tothread1-3!Thread1:Sendthread2:thread1tothread2-4!Thread2:Sendthread3:thread2tothread3-4!Thread3:Sendthread1:thread3tothread1-4!Thread1:Sendthread2:thread1tothread2-5!Thread2:Sendthread3:thread2tothread3-5!Thread3:Sendthread1:thread3tothread1-5!Thread1:Recvivemessage:thread3tothread1-1!Thread2:Recvivemessage:thread1tothread2-1!Thread3:Recvivemessage:thread2tothread3-1!Thread1:Recvivemessage:thread3tothread1-2!Thread2:Recvivemessage:thread1tothread2-2!Thread3:Recvivemessage:thread2tothread3-2!Thread1:Recvivemessage:thread3tothread1-3!Thread2:Recvivemessage:thread1tothread2-3!Thread3:Recvivemessage:thread2tothread3-3!Thread1:Recvivemessage:thread3tothread1-4!Thread2:Recvivemessage:thread1tothread2-4!Thread3:Recvivemessage:thread2tothread3-4!Thread1:Recvivemessage:thread3tothread1-5!Thread2:Recvivemessage:thread1tothread2-5!Thread3:Recvivemessage:thread2tothread3-5!============Thread1isover!============Thread2isover!============Thread3isover!2、生產(chǎn)者消費(fèi)者問題的實(shí)現(xiàn)結(jié)果如下:current=1prodece1produce_cnt=0consume_cnt=0production=2209current=1prodece2produce_cnt=1consume_cnt=0production=2209current=1prodece1produce_cnt=1consume_cnt=0production=961current=1prodece2produce_cnt=2consume_cnt=0production=961current=1prodece1produce_cnt=2consume_cnt=0production=1089current=1prodece2produce_cnt=3consume_cnt=0production=1089current=1prodece1produce_cnt=3consume_cnt=0production=1681current=1prodece2produce_cnt=4consume_cnt=0production=1681current=1prodece1produce_cnt=4consume_cnt=0production=49current=1prodece2produce_cnt=5consume_cnt=0production=49current=1prodece1produce_cnt=5consume_cnt=0production=324Thread1isblocked!current=2consume1produce_cnt=5consume_cnt=0production=324current=2consume2produce_cnt=5consume_cnt=1production=324Blockqueueisempty!Thread1hasbeenwakedup!current=1prodece2produce_cnt=6consume_cnt=1production=324current=1prodece1produce_cnt=6consume_cnt=1production=2116Thread1isblocked!current=2consume1produce_cnt=6consume_cnt=1production=2116current=2consume2produce_cnt=6consume_cnt=2production=2116Blockqueueisempty!Thread1hasbeenwakedup!current=1prodece2produce_cnt=7consume_cnt=2production=2116current=1prodece1produce_cnt=7consume_cnt=2production=256Thread1isblocked!current=2consume1produce_cnt=7consume_cnt=2production=256current=2consume2produce_cnt=7consume_cnt=3production=256Blockqueueisempty!Thread1hasbeenwakedup!current=1prodece2produce_cnt=8consume_cnt=3production=256current=1prodece1produce_cnt=8consume_cnt=3production=2401Thread1isblocked!current=2consume1produce_cnt=8consume_cnt=3production=2401current=2consume2produce_cnt=8consume_cnt=4production=2401Blockqueueisempty!Thread1hasbeenwakedup!current=1prodece2produce_cnt=9consume_cnt=4production=2401current=1prodece1produce_cnt=9consume_cnt=4production=729Thread1isblocked!current=2consume1produce_cnt=9consume_cnt=4production=729current=2consume2produce_cnt=9consume_cnt=5production=729Blockqueueisempty!Thread1hasbeenwakedup!current=1prodece2produce_cnt=10consume_cnt=5production=729============Thread1isover!current=2consume1produce_cnt=10consume_cnt=5production=729current=2consume2produce_cnt=10consume_cnt=6production=729current=2consume1produce_cnt=10consume_cnt=6production=729current=2consume2produce_cnt=10consume_cnt=7production=729current=2consume1produce_cnt=10consume_cnt=7production=729current=2consume2produce_cnt=10consume_cnt=8production=729current=2consume1produce_cnt=10consume_cnt=8production=729current=2consume2produce_cnt=10consume_cnt=9production=72
任務(wù)二、簡單文件系統(tǒng)程序的設(shè)計(jì)一、實(shí)驗(yàn)?zāi)康谋緦?shí)驗(yàn)旨在通過編程實(shí)現(xiàn)簡單的文件系統(tǒng)促進(jìn)對于文件系統(tǒng)的概念和實(shí)現(xiàn)的理解。這里的簡單文件系統(tǒng)可以是自己設(shè)計(jì)的,以下我們將以FAT16做為基本的實(shí)現(xiàn)對象,可以進(jìn)行適當(dāng)?shù)暮喕幚?。二、?shí)驗(yàn)要求本實(shí)驗(yàn)要求實(shí)現(xiàn)如下要求:1.設(shè)計(jì)實(shí)現(xiàn)基于FAT的簡單文件系統(tǒng)2.實(shí)現(xiàn)文件的若干常用命令。三、已經(jīng)實(shí)現(xiàn)的功能1.設(shè)計(jì)實(shí)現(xiàn)基于FAT的簡單文件系統(tǒng)2.實(shí)現(xiàn)文件的若干常用命令,包括:format:格式化文件系統(tǒng)。ls:列出當(dāng)前目錄中的內(nèi)容。cd:切換目錄。mkdir:創(chuàng)建新目錄。rmdir:刪除目錄。create:創(chuàng)建新文件。read:讀文件內(nèi)容。write:向文件中寫入數(shù)據(jù)。open:打開文件。close:關(guān)閉文件。rm:刪除文件。四、未能實(shí)現(xiàn)的功能未實(shí)現(xiàn)在當(dāng)前目錄下刪除父目錄文件五、程序設(shè)計(jì)思路與代碼分析本程序?qū)崿F(xiàn)了一種類似于FAT12的簡單文件系統(tǒng),但每個FAT表項(xiàng)只占8位,它以盤塊為基本分配單位,每個盤塊(BLOCK_SIZE)大小為512字節(jié)。最開始的第0塊為引導(dǎo)塊。接下來的是兩張F(tuán)AT表,每個FAT表項(xiàng)長度為8位,即最大的磁盤容量為256*BLOCK_SIZE字節(jié)。每張F(tuán)AT表共有256個表項(xiàng),因此兩張F(tuán)AT表剛好是512字節(jié),也即一個BLOCK_SIZE。接下來的第2塊就是根目錄了,在格式化的時候,根目錄中已經(jīng)被增入兩個目錄項(xiàng):”.”和”..”,分別表示當(dāng)前目錄和上層目錄。(一)MY-FAT8的主要結(jié)構(gòu):
(二)FAT表:
FAT表項(xiàng)中的內(nèi)容表示了文件的下一個盤塊號,如果文件已經(jīng)沒有下一個盤塊了,則相應(yīng)的表項(xiàng)內(nèi)容為0xFF(END_OF_FILE),表示文件結(jié)束。如果FAT表項(xiàng)的內(nèi)容為0(NOT_USED),則表示該表項(xiàng)對應(yīng)的塊尚未被使用。(三)文件控制塊(FAT_entry):
每個文件都有一個文件控制塊,大小為16字節(jié)。
structFAT_entry
{
charname[MAX_NAME];
//文件名
#defineMAX_NAME
10
unsignedcharattr;
//文件屬性
unsignedcharfstblk;
//文件所在的第一個塊的塊號
int
filesize;
//文件大小
};
文件的屬性有:ATTR_DIRECTORY(表示文件是個目錄),ATTR_FILE(普通文件),ATTR_READ(只讀文件),ATTR_WRITE(可寫),ATTR_READ_WRITE(讀寫)。這些屬性有些可以通過”|”運(yùn)算進(jìn)行組合。(四)文件打開表(opentable):
由open_table指向的單向鏈表組成,第一項(xiàng)都表示了一個打開的文件,opentabel結(jié)構(gòu)體中blk和off表示當(dāng)前該打開文件的操作位置(下一次讀或?qū)懖僮鲗倪@里開始,每次讀或?qū)懖僮髦筮@兩個值都會改變)。(五)主要操作的實(shí)現(xiàn):
1.format格式化
由于文件系統(tǒng)是虛擬在內(nèi)存中的,所以操作相對較容易。只要將所有FAT表項(xiàng)的內(nèi)容置為NOT_USED(第0~2塊的FAT表項(xiàng)當(dāng)然要置為END_OF_FILE了),并在根目錄中填好”.”和”..”項(xiàng)的內(nèi)容即可。voidformat(){ unsignedchar*temp; dir_entry*tem; fat_table=(unsignedchar*)(fdisk+BLOCK_SIZE); dir_table=(char*)(fat_table+FAT_ENTRY_NUM*2); for(temp=fat_table;temp<(unsignedchar*)dir_table;temp++) *temp=NOT_USED; *fat_table =END_OF_FILE; //第0塊->引導(dǎo)塊 *(fat_table+1) =END_OF_FILE; //第1塊->兩張F(tuán)AT表 *(fat_table+2) =END_OF_FILE; //第2塊->根目錄 root=(dir_entry*)dir_table; tem=root; strcpy(tem->name,"."); //設(shè)置當(dāng)前目錄 tem->attr=ATTR_DIRECTORY; //屬性為目錄 tem->filesize=32; //當(dāng)前目錄大小為32字節(jié) tem->fstblk=2; //當(dāng)前目錄開始塊號為2 tem++; strcpy(tem->name,".."); //設(shè)置上層目錄 tem->attr=ATTR_DIRECTORY; tem->filesize=0; tem->fstblk=END_OF_FILE; //根目錄沒有上層目錄}2.namei
這個操作主要是由一個路徑path找到它對應(yīng)的文件的文件控制塊。如path為:a\b\c那么這個操作就返回:當(dāng)前目錄\a\b\目錄下的c文件的文件控制塊。主要的實(shí)現(xiàn)思路是:找到兩個”\”之間的目錄名,如:a,從當(dāng)前查找目錄里找這個目錄,如果沒找到則返回錯誤,如果找到則把a(bǔ)目錄設(shè)為當(dāng)前查找目錄,繼續(xù)遞歸地找,直到找到path的最后一項(xiàng)。在查找中要注意一個目錄文件的長度可能大于一個塊,這樣就要求在FAT表中獲得目錄文件下一塊的塊號。dir_entry*namei(constchar*path){ chartemp[MAX_NAME]={0}; inti,j,len,left,block; boolsuccess; dir_entry*de,*dt,*dir; if(path[0]=='\0')returncurr_dir; dir=curr_dir; len=strlen(path); i=path[0]=='\\'?1:0; for(j=0;i<=len;i++) { if(path[i]=='\\'||path[i]=='\0') // 找到temp[] { temp[j]='\0'; success=0; dt=(dir_entry*)(fdisk+BLOCK_SIZE*dir->fstblk); block=dir->fstblk; while(*(fat_table+block)!=END_OF_FILE)//如果目錄長度大于1塊 { left=BLOCK_SIZE; for(de=dt;left>0;de++,left-=DIR_ENTRY_SIZE) { if(!strcmp(de->name,temp)) { dir=de; success=1; break; } } if(success)break; block=*(fat_table+block); dt=(dir_entry*)(fdisk+BLOCK_SIZE*block); } if(success) { j=0; continue; } left=dir->filesize%BLOCK_SIZE; if(left==0)left=BLOCK_SIZE; for(de=dt;left>0;de++,left-=DIR_ENTRY_SIZE) { if(!strcmp(de->name,temp)) { dir=de; success=1; break; } } if(!success) { printf("Error:Cannotfinddirectory/file:%s!\n",temp); returnNULL; } j=0; continue; } temp[j]=path[i]; j++; } returndir;}3.create
創(chuàng)建一個文件
創(chuàng)建一個文件要做兩件事情:1.判斷該文件是否已經(jīng)存在。2.創(chuàng)建文件。
假設(shè)要創(chuàng)建的文件路徑是:a\b\c,那么首先到curr_dir\a\b目錄下找c文件(如果連這個目錄都沒找到那肯定要返回錯誤了),如果找到說明c文件已經(jīng)存在,否則為c文件分配空閑的文件控制塊并填寫相應(yīng)的屬性等信息(如果curr_dir\a\b目錄中已經(jīng)沒有空間存放文件控制塊了則要申請一個新的塊,并修改FAT表項(xiàng)的內(nèi)容)。如果創(chuàng)建的是目錄文件則要為它申請新的一塊,并在塊中填入”.”和”..”項(xiàng)的內(nèi)容。由此可見,創(chuàng)建一個普通文件和創(chuàng)建一個目錄是不同的,普通文件的初始大小為0,初始塊號為END_OF_FILE,而目錄文件的初始大小為32,初始塊號為getblk()返回的值。dir_entry*create(constchar*path,unsignedcharattr){ inti,left,block; dir_entry*de,*dt,*dir,*tem; charname[MAX_NAME]; chart_path[MAX_PATH]; strcpy(t_path,path); for(i=strlen(path)-1;i>=0;i--) if(path[i]=='\\')break; strcpy(name,path+i+1); if(i<0)i=0; t_path[i]='\0'; dir=namei(t_path); if(dir==NULL)returnNULL; if(strlen(name)>MAX_NAME) //檢查文件名長度 { printf("Error:Nameistoolong!\n"); returnNULL; } block=dir->fstblk; dt=(dir_entry*)(fdisk+BLOCK_SIZE*block); while(*(fat_table+block)!=END_OF_FILE) //如果當(dāng)前目錄長度大于1塊 { left=BLOCK_SIZE; for(de=dt;left>0;de++,left-=DIR_ENTRY_SIZE) { if(!strcmp(de->name,name)) { printf("Error:Filealreadyexsists!\n"); returnNULL; } } block=*(fat_table+block); dt=(dir_entry*)(fdisk+BLOCK_SIZE*block); } left=dir->filesize%BLOCK_SIZE; if(left==0) //空間不足則重新申請一塊 { *(fat_table+block)=getblk(); if(*(fat_table+block)==END_OF_FILE)returnNULL; //找不到空閑塊 block=*(fat_table+block); *(fat_table+block)=END_OF_FILE; dt=(dir_entry*)(fdisk+BLOCK_SIZE*block); } for(de=dt;left>0;de++,left-=DIR_ENTRY_SIZE) { if(!strcmp(de->name,name)) { printf("Error:Filealreadyexsists!\n"); returnNULL; } } //de++; dir->filesize+=DIR_ENTRY_SIZE; strcpy(de->name,name); de->attr=attr; if(attr&ATTR_DIRECTORY) //如果所創(chuàng)建的是文件夾 { block=getblk(); de->fstblk=block; if(block==END_OF_FILE) { printf("Error:Failedtomakedirectory!\n"); returnNULL; } de->filesize=32; tem=(dir_entry*)(fdisk+BLOCK_SIZE*block); strcpy(tem->name,"."); //設(shè)置當(dāng)前目錄 tem->attr=ATTR_DIRECTORY; //屬性為目錄 tem->filesize=32; //當(dāng)前目錄大小為32字節(jié) tem->fstblk=block; //當(dāng)前目錄開始塊號為block tem++; strcpy(tem->name,".."); //設(shè)置上層目錄 tem->attr=ATTR_DIRECTORY; tem->filesize=dir->filesize; tem->fstblk=dir->fstblk; } else //所創(chuàng)建的是文件 { de->fstblk=END_OF_FILE; //文件初始塊為END_OF_FILE de->filesize=0; //文件初始大小為0 } returnde;}4.rm
刪除一個文件
與create類似。
刪除一個文件的時候,為保持目錄中有效FAT_entry的連續(xù)性,將最后一條有效FAT_entry的內(nèi)容拷備到要刪除FAT_entry中來,并刪除最后一條FAT_rm(constchar*path){ inti,left,block; dir_entry*dt,*de,*lastentry,*dir; charname[MAX_NAME]; chart_path[MAX_PATH]; strcpy(t_path,path); for(i=strlen(path)-1;i>=0;i--) if(path[i]=='\\')break; strcpy(name,path+i+1); if(i<0)i=0; t_path[i]='\0'; dir=namei(t_path); if(dir==NULL)returnNULL; if(strlen(name)>MAX_NAME) //檢查文件名長度 { printf("Error:Nameistoolong!\n"); return0; } //找最后一條dir_entry lastentry=NULL; block=dir->fstblk; while(*(fat_table+block)!=END_OF_FILE) block=*(fat_table+block); lastentry=(dir_entry*)(fdisk+BLOCK_SIZE*block+(dir->filesize-DIR_ENTRY_SIZE)%BLOCK_SIZE); block=dir->fstblk; dt=(dir_entry*)(fdisk+BLOCK_SIZE*block); while(*(fat_table+block)!=END_OF_FILE) //如果當(dāng)前目錄長度大于1塊 { left=BLOCK_SIZE; for(de=dt;left>0;de++,left-=DIR_ENTRY_SIZE) { if(!strcmp(de->name,name)) { if(de->attr&ATTR_DIRECTORY&&de->filesize>32) { printf("Error:Cannotremovedirectory!%sisnotempty!\n",de->name); return0; } releaseblock(de->fstblk); strcpy(de->name,lastentry->name); //將要刪除的dir_entry與最后一條dir_entry互換 de->attr=lastentry->attr; de->filesize=lastentry->filesize; de->fstblk=lastentry->fstblk; lastentry->name[0]='\0'; lastentry->fstblk=END_OF_FILE; lastentry->filesize=0; lastentry->attr=0; dir->filesize-=DIR_ENTRY_SIZE; return1; } } block=*(fat_table+block); dt=(dir_entry*)(fdisk+BLOCK_SIZE*block); } left=dir->filesize%BLOCK_SIZE; if(left==0)left=BLOCK_SIZE; for(de=dt;left>0;de++,left-=DIR_ENTRY_SIZE) { if(!strcmp(de->name,name)) { releaseblock(de->fstblk); strcpy(de->name,lastentry->name); //將要刪除的dir_entry與最后一條dir_entry互換 de->attr=lastentry->attr; de->filesize=lastentry->filesize; de->fstblk=lastentry->fstblk; lastentry->name[0]='\0'; lastentry->fstblk=END_OF_FILE; lastentry->filesize=0; lastentry->attr=0; dir->filesize-=DIR_ENTRY_SIZE; return1; } } printf("Error:Cannotfindfile:%s!\n",name); return0;}5.open
打開一個文件
首先檢查下文件是否已經(jīng)打開。如果沒有打開,則由文件對應(yīng)的path,利namei(path)找到要打開的文件的文件控制塊,并加到到open_table(文件打開表)中去。
opentable的結(jié)構(gòu):
structopentable
{
FAT_entry*file;
//打開的文件控制塊
unsignedcharop_attr;
//打開的文件的屬性
int
blk;
//文件指針?biāo)诘膲K
int
off;
//文件指針?biāo)诘膲K內(nèi)偏移
opentable*next;
//指向下一個打開文件表項(xiàng)
}
opentable中blk及off表示了當(dāng)前對此打開的文件的操作己經(jīng)處于該文件所占磁盤空間的第blk塊中的第off個字節(jié)的位置。剛打開文件的時候這兩個值當(dāng)然都是0了。6.close
關(guān)閉一個文件
與open類似。7.read
從指定的文件中讀size個字節(jié)到緩沖區(qū)中
首先判斷指定的文件是否已經(jīng)打開。若文件已打開,再由namei(path)找到文件控制塊,開始遞歸讀文件中的數(shù)據(jù)。在讀完文件之后,要修改文件打開表中當(dāng)前操作(即blk和off)的值。如果要讀的字節(jié)數(shù)size已經(jīng)起過文件最大長度,則讀到文件結(jié)尾為止。
最后,返回實(shí)際所讀的字節(jié)數(shù)。intread(opentable*openfile,char*buffer,intsize){ if(!fileopened(openfile)) { printf("Error:File:%sisnotopened!\n",openfile->file->name); return0; } if(!(openfile->op_attr&ATTR_READ)) // 文件是否有讀權(quán)限 { printf("Error:Cannotreadthefile!\n"); return0; } if(size==0)return0; if(openfile->blk==END_OF_FILE) { printf("Error:File:%sisempty!\n",openfile->file->name); return0; } //openfile->blk=openfile->file->fstblk; //openfile->off=0; returnreadblk(openfile,buffer,size);}8.write
從緩沖區(qū)中寫size個字節(jié)到指定的文件中
與read操作類似。
在文件剛被創(chuàng)建時,普通文件的size是為0的,因此,若對一個剛被創(chuàng)建的普通文件進(jìn)行write操作,必須先申請一個空閑塊,再進(jìn)行遞歸的寫操作。而對于剛被創(chuàng)建的目錄文件卻沒有這個問題,因?yàn)槟夸浳募粍?chuàng)建的時候size為32(有”.”和”..”兩個目錄項(xiàng)了)。intwrite(opentable*openfile,constchar*buffer,intsize){ intblock; if(!fileopened(openfile)) { printf("Error:File:%sisnotopened!\n",openfile->file->name); return0; } if(!(openfile->op_attr&ATTR_WRITE)) // 文件是否有讀權(quán)限 { printf("Error:Cannotwritethefile!\n"); return0; } if(size==0)return0; if(openfile->blk==END_OF_FILE) // 如果文件為空則為文件分配一個空閑塊 { openfile->blk=getblk(); openfile->file->fstblk=openfile->blk; // 修改文件起始塊塊號 openfile->off=0; } intleft,i=0; block=openfile->file->fstblk; while(block!=openfile->blk) { block=*(fat_table+block); i++; } left=op
溫馨提示
- 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)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年空壓式輪焊機(jī)項(xiàng)目可行性研究報(bào)告
- 2025年企業(yè)安全管理人員安全培訓(xùn)考試試題含答案【基礎(chǔ)題】
- 25年車間職工安全培訓(xùn)考試試題含答案【考試直接用】
- 2025年崗位安全培訓(xùn)考試試題及完整答案(名校卷)
- 2025員工安全培訓(xùn)考試試題及答案突破訓(xùn)練
- 2025年盤槐項(xiàng)目可行性研究報(bào)告
- 2025年電視機(jī)調(diào)諧器項(xiàng)目可行性研究報(bào)告
- 2025年電磁調(diào)速異步電動機(jī)項(xiàng)目可行性研究報(bào)告
- 2025年幼兒園中班下學(xué)期社交技能計(jì)劃
- 水務(wù)管理中心值守人員崗位職責(zé)
- 2025年開封大學(xué)單招職業(yè)技能測試題庫及答案1套
- 小學(xué)教師招聘-《小學(xué)教育學(xué)》押題密卷1
- 《InSAR干涉測量》課件
- 2025年腦機(jī)接口藍(lán)皮書:未來將至打造人機(jī)交互新范式-前瞻研究院
- 工程地質(zhì)學(xué)知到智慧樹章節(jié)測試課后答案2024年秋廣東工業(yè)大學(xué)
- 2025-2030年中國牛黃市場發(fā)展?fàn)顩r與前景投資策略建議報(bào)告
- DBJ33T 1307-2023 微型鋼管樁加固技術(shù)規(guī)程
- 邏輯哲學(xué)論中文版分享
- 廣東省深圳市南山區(qū)2023-2024學(xué)年六年級上學(xué)期英語期末試卷
- 2025年八省聯(lián)考高考數(shù)學(xué)試卷評析及復(fù)習(xí)備考指導(dǎo)課件
- 日立電梯LCA故障代碼
評論
0/150
提交評論