




版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
董永文07057409-操作系統(tǒng)課程設(shè)計(jì)實(shí)驗(yàn)報(bào)告姓名:董永文專(zhuān)業(yè):軟件工程班級(jí):07052714學(xué)號(hào):070574092010年7月
任務(wù)一、基于線程的多任務(wù)程序設(shè)計(jì)一、實(shí)驗(yàn)?zāi)康谋緦?shí)驗(yàn)旨在促進(jìn)對(duì)于線程控制、調(diào)度算法和消息通信機(jī)制的理解。這里的多線程并不使用任何的操作系統(tǒng)提供的線程系統(tǒng)調(diào)用,而是依靠自己的線程相關(guān)函數(shù)完成上述目標(biāo),線程的調(diào)度依靠的是改造后的時(shí)鐘中斷處理程序來(lái)實(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)者問(wèn)題的實(shí)現(xiàn)因此本程序可以以上功能實(shí)現(xiàn)先后順序?yàn)樵O(shè)計(jì)思路,進(jìn)行代碼編寫(xiě)。(一)線程的創(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)識(shí)符*/
char
name[10];/*NTCB是系統(tǒng)允許的最多任務(wù)個(gè)數(shù)*/structbuffer *mq;/*消息隊(duì)列隊(duì)首指針,初值為NULL*/
structsemaphoremutex;
/*消息隊(duì)列的互拆信號(hào)量,初值為{1,NULL}*/
structsemaphoresm;
/*消息隊(duì)列的計(jì)數(shù)信號(hào)量,初值為{0,NULL}*/intreaderNum;/*當(dāng)線程作為讀線程時(shí)所讀線程的線程內(nèi)部標(biāo)識(shí)符*/
}tcb[NTCB];2、創(chuàng)建線程:線程創(chuàng)建的一般步驟
1.為新線程分配一個(gè)線程控制塊,TCB數(shù)組的下標(biāo)即為該線程的內(nèi)部標(biāo)識(shí)符。
2.為新線程分配私有堆??臻g。
3.初始化新線程的私有堆棧,即按CPU調(diào)度時(shí)現(xiàn)場(chǎng)信息的保存格式布置堆棧。
4.初始化線程控制塊。
5.其它工作。如按優(yōu)先級(jí)進(jìn)行CPU調(diào)度,則需在TCB中加上優(yōu)先權(quán)信息。
6.返回新線程的內(nèi)部標(biāo)識(shí)符。為新線程分配私有堆棧空間intcreate(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)利用時(shí)鐘中斷來(lái)進(jìn)行CPU調(diào)度,設(shè)計(jì)中要注意:新中斷處理程序不能太長(zhǎng),否則系統(tǒng)效率將大大降低甚至使系統(tǒng)無(wú)法正常工作;在新的時(shí)鐘中斷處理程序里必須調(diào)用系統(tǒng)原來(lái)的INT08H,否則將影響磁盤(pán)馬達(dá)和系統(tǒng)的計(jì)時(shí)。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)用原來(lái)的中斷處理程序*/
(*old_int8)();
timecount++;
/*優(yōu)先級(jí)加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)程的阻塞和喚醒線程阻塞過(guò)程:將線程的狀態(tài)改成阻塞態(tài),將線程插入指定的阻塞隊(duì)列末尾,并重新進(jìn)行CPU調(diào)度。
線程喚醒過(guò)程:把阻塞隊(duì)列頭上的第一個(gè)線程的TCB取下來(lái),并將其狀態(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è)剛開(kāi)始時(shí)系統(tǒng)中有NBUF個(gè)消息緩沖區(qū),它們排成一個(gè)消息隊(duì)列freebuf,為實(shí)現(xiàn)對(duì)該隊(duì)列操作的互斥,設(shè)置信號(hào)量mutexb(初值為{1,NULL})。
發(fā)送消息時(shí),發(fā)送者必須提供接收者的標(biāo)識(shí)符、消息的長(zhǎng)度及消息正文的起始地址等信息。
接收消息時(shí),接收者必須指出發(fā)送者的標(biāo)識(shí)符、接收區(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開(kāi)始的size個(gè)字節(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ā)送來(lái)的消息到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)者問(wèn)題的實(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)者問(wèn)題的實(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ù)二、簡(jiǎn)單文件系統(tǒng)程序的設(shè)計(jì)一、實(shí)驗(yàn)?zāi)康谋緦?shí)驗(yàn)旨在通過(guò)編程實(shí)現(xiàn)簡(jiǎn)單的文件系統(tǒng)促進(jìn)對(duì)于文件系統(tǒng)的概念和實(shí)現(xiàn)的理解。這里的簡(jiǎn)單文件系統(tǒng)可以是自己設(shè)計(jì)的,以下我們將以FAT16做為基本的實(shí)現(xiàn)對(duì)象,可以進(jìn)行適當(dāng)?shù)暮?jiǎn)化處理。二、實(shí)驗(yàn)要求本實(shí)驗(yàn)要求實(shí)現(xiàn)如下要求:1.設(shè)計(jì)實(shí)現(xiàn)基于FAT的簡(jiǎn)單文件系統(tǒng)2.實(shí)現(xiàn)文件的若干常用命令。三、已經(jīng)實(shí)現(xiàn)的功能1.設(shè)計(jì)實(shí)現(xiàn)基于FAT的簡(jiǎn)單文件系統(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:向文件中寫(xiě)入數(shù)據(jù)。open:打開(kāi)文件。close:關(guān)閉文件。rm:刪除文件。四、未能實(shí)現(xiàn)的功能未實(shí)現(xiàn)在當(dāng)前目錄下刪除父目錄文件五、程序設(shè)計(jì)思路與代碼分析本程序?qū)崿F(xiàn)了一種類(lèi)似于FAT12的簡(jiǎn)單文件系統(tǒng),但每個(gè)FAT表項(xiàng)只占8位,它以盤(pán)塊為基本分配單位,每個(gè)盤(pán)塊(BLOCK_SIZE)大小為512字節(jié)。最開(kāi)始的第0塊為引導(dǎo)塊。接下來(lái)的是兩張F(tuán)AT表,每個(gè)FAT表項(xiàng)長(zhǎng)度為8位,即最大的磁盤(pán)容量為256*BLOCK_SIZE字節(jié)。每張F(tuán)AT表共有256個(gè)表項(xiàng),因此兩張F(tuán)AT表剛好是512字節(jié),也即一個(gè)BLOCK_SIZE。接下來(lái)的第2塊就是根目錄了,在格式化的時(shí)候,根目錄中已經(jīng)被增入兩個(gè)目錄項(xiàng):”.”和”..”,分別表示當(dāng)前目錄和上層目錄。(一)MY-FAT8的主要結(jié)構(gòu):
(二)FAT表:
FAT表項(xiàng)中的內(nèi)容表示了文件的下一個(gè)盤(pán)塊號(hào),如果文件已經(jīng)沒(méi)有下一個(gè)盤(pán)塊了,則相應(yīng)的表項(xiàng)內(nèi)容為0xFF(END_OF_FILE),表示文件結(jié)束。如果FAT表項(xiàng)的內(nèi)容為0(NOT_USED),則表示該表項(xiàng)對(duì)應(yīng)的塊尚未被使用。(三)文件控制塊(FAT_entry):
每個(gè)文件都有一個(gè)文件控制塊,大小為16字節(jié)。
structFAT_entry
{
charname[MAX_NAME];
//文件名
#defineMAX_NAME
10
unsignedcharattr;
//文件屬性
unsignedcharfstblk;
//文件所在的第一個(gè)塊的塊號(hào)
int
filesize;
//文件大小
};
文件的屬性有:ATTR_DIRECTORY(表示文件是個(gè)目錄),ATTR_FILE(普通文件),ATTR_READ(只讀文件),ATTR_WRITE(可寫(xiě)),ATTR_READ_WRITE(讀寫(xiě))。這些屬性有些可以通過(guò)”|”運(yùn)算進(jìn)行組合。(四)文件打開(kāi)表(opentable):
由open_table指向的單向鏈表組成,第一項(xiàng)都表示了一個(gè)打開(kāi)的文件,opentabel結(jié)構(gòu)體中blk和off表示當(dāng)前該打開(kāi)文件的操作位置(下一次讀或?qū)懖僮鲗倪@里開(kāi)始,每次讀或?qū)懖僮髦筮@兩個(gè)值都會(huì)改變)。(五)主要操作的實(shí)現(xiàn):
1.format格式化
由于文件系統(tǒng)是虛擬在內(nèi)存中的,所以操作相對(duì)較容易。只要將所有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)前目錄開(kāi)始?jí)K號(hào)為2 tem++; strcpy(tem->name,".."); //設(shè)置上層目錄 tem->attr=ATTR_DIRECTORY; tem->filesize=0; tem->fstblk=END_OF_FILE; //根目錄沒(méi)有上層目錄}2.namei
這個(gè)操作主要是由一個(gè)路徑path找到它對(duì)應(yīng)的文件的文件控制塊。如path為:a\b\c那么這個(gè)操作就返回:當(dāng)前目錄\a\b\目錄下的c文件的文件控制塊。主要的實(shí)現(xiàn)思路是:找到兩個(gè)”\”之間的目錄名,如:a,從當(dāng)前查找目錄里找這個(gè)目錄,如果沒(méi)找到則返回錯(cuò)誤,如果找到則把a(bǔ)目錄設(shè)為當(dāng)前查找目錄,繼續(xù)遞歸地找,直到找到path的最后一項(xiàng)。在查找中要注意一個(gè)目錄文件的長(zhǎng)度可能大于一個(gè)塊,這樣就要求在FAT表中獲得目錄文件下一塊的塊號(hào)。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)//如果目錄長(zhǎng)度大于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)建一個(gè)文件
創(chuàng)建一個(gè)文件要做兩件事情:1.判斷該文件是否已經(jīng)存在。2.創(chuàng)建文件。
假設(shè)要?jiǎng)?chuàng)建的文件路徑是:a\b\c,那么首先到curr_dir\a\b目錄下找c文件(如果連這個(gè)目錄都沒(méi)找到那肯定要返回錯(cuò)誤了),如果找到說(shuō)明c文件已經(jīng)存在,否則為c文件分配空閑的文件控制塊并填寫(xiě)相應(yīng)的屬性等信息(如果curr_dir\a\b目錄中已經(jīng)沒(méi)有空間存放文件控制塊了則要申請(qǐng)一個(gè)新的塊,并修改FAT表項(xiàng)的內(nèi)容)。如果創(chuàng)建的是目錄文件則要為它申請(qǐng)新的一塊,并在塊中填入”.”和”..”項(xiàng)的內(nèi)容。由此可見(jiàn),創(chuàng)建一個(gè)普通文件和創(chuàng)建一個(gè)目錄是不同的,普通文件的初始大小為0,初始?jí)K號(hào)為END_OF_FILE,而目錄文件的初始大小為32,初始?jí)K號(hào)為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) //檢查文件名長(zhǎng)度 { printf("Error:Nameistoolong!\n"); returnNULL; } block=dir->fstblk; dt=(dir_entry*)(fdisk+BLOCK_SIZE*block); while(*(fat_table+block)!=END_OF_FILE) //如果當(dāng)前目錄長(zhǎ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) //空間不足則重新申請(qǐng)一塊 { *(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)前目錄開(kāi)始?jí)K號(hào)為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; //文件初始?jí)K為END_OF_FILE de->filesize=0; //文件初始大小為0 } returnde;}4.rm
刪除一個(gè)文件
與create類(lèi)似。
刪除一個(gè)文件的時(shí)候,為保持目錄中有效FAT_entry的連續(xù)性,將最后一條有效FAT_entry的內(nèi)容拷備到要?jiǎng)h除FAT_entry中來(lái),并刪除最后一條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) //檢查文件名長(zhǎng)度 { 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)前目錄長(zhǎ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); //將要?jiǎng)h除的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); //將要?jiǎng)h除的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
打開(kāi)一個(gè)文件
首先檢查下文件是否已經(jīng)打開(kāi)。如果沒(méi)有打開(kāi),則由文件對(duì)應(yīng)的path,利namei(path)找到要打開(kāi)的文件的文件控制塊,并加到到open_table(文件打開(kāi)表)中去。
opentable的結(jié)構(gòu):
structopentable
{
FAT_entry*file;
//打開(kāi)的文件控制塊
unsignedcharop_attr;
//打開(kāi)的文件的屬性
int
blk;
//文件指針?biāo)诘膲K
int
off;
//文件指針?biāo)诘膲K內(nèi)偏移
opentable*next;
//指向下一個(gè)打開(kāi)文件表項(xiàng)
}
opentable中blk及off表示了當(dāng)前對(duì)此打開(kāi)的文件的操作己經(jīng)處于該文件所占磁盤(pán)空間的第blk塊中的第off個(gè)字節(jié)的位置。剛打開(kāi)文件的時(shí)候這兩個(gè)值當(dāng)然都是0了。6.close
關(guān)閉一個(gè)文件
與open類(lèi)似。7.read
從指定的文件中讀size個(gè)字節(jié)到緩沖區(qū)中
首先判斷指定的文件是否已經(jīng)打開(kāi)。若文件已打開(kāi),再由namei(path)找到文件控制塊,開(kāi)始遞歸讀文件中的數(shù)據(jù)。在讀完文件之后,要修改文件打開(kāi)表中當(dāng)前操作(即blk和off)的值。如果要讀的字節(jié)數(shù)size已經(jīng)起過(guò)文件最大長(zhǎ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ū)中寫(xiě)size個(gè)字節(jié)到指定的文件中
與read操作類(lèi)似。
在文件剛被創(chuàng)建時(shí),普通文件的size是為0的,因此,若對(duì)一個(gè)剛被創(chuàng)建的普通文件進(jìn)行write操作,必須先申請(qǐng)一個(gè)空閑塊,再進(jìn)行遞歸的寫(xiě)操作。而對(duì)于剛被創(chuàng)建的目錄文件卻沒(méi)有這個(gè)問(wèn)題,因?yàn)槟夸浳募粍?chuàng)建的時(shí)候size為32(有”.”和”..”兩個(gè)目錄項(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) // 如果文件為空則為文件分配一個(gè)空閑塊 { openfile->blk=getblk(); openfile->file->fstblk=openfile->blk; // 修改文件起始?jí)K塊號(hào) openfile->off=0; } intleft,i=0; block=openfile->file->fstblk; while(block!=openfile->blk) { block=*(fat_table+block); i++; } left=op
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 路邊砍樹(shù)協(xié)議書(shū)范本
- 退房合同收據(jù)和訂購(gòu)協(xié)議
- 輕質(zhì)磚合同協(xié)議
- 煤渣處理協(xié)議書(shū)
- 軟件實(shí)施補(bǔ)充合同協(xié)議
- 木材合股協(xié)議書(shū)
- 進(jìn)口水果批發(fā)合同協(xié)議
- 個(gè)人郵箱服務(wù)授權(quán)協(xié)議
- 技術(shù)專(zhuān)利權(quán)轉(zhuǎn)讓服務(wù)合同
- 建筑工程招投標(biāo)與合同管理作業(yè)
- 一年級(jí)下冊(cè)動(dòng)物王國(guó)開(kāi)大會(huì)課件
- 《用戶(hù)畫(huà)像-大數(shù)據(jù)時(shí)代的買(mǎi)家思維營(yíng)銷(xiāo)》讀書(shū)筆記
- 高原疾病急救培訓(xùn)課件
- 產(chǎn)婦護(hù)理膿毒血癥
- 唐代文學(xué)中的植物書(shū)寫(xiě)研究
- 2023年英語(yǔ)四級(jí)聽(tīng)力真題(第一套)題目-原文與答案
- 有機(jī)化學(xué)(下)實(shí)驗(yàn)操作考試試題 標(biāo)準(zhǔn)答案和評(píng)分標(biāo)準(zhǔn)
- 船舶概論課件
- 兒童哮喘疾病宣傳海報(bào)
- 大學(xué)生創(chuàng)業(yè)基礎(chǔ)智慧樹(shù)知到課后章節(jié)答案2023年下湖北工業(yè)大學(xué)
- 當(dāng)代實(shí)驗(yàn)影像藝術(shù)的研究與探索
評(píng)論
0/150
提交評(píng)論