【課程設(shè)計|C++】操作系統(tǒng):文件系統(tǒng)
文件系統(tǒng)
題目描述
1、實驗內(nèi)容
通過一個簡單的二級文件系統(tǒng)設(shè)計,加深對文件系統(tǒng)的內(nèi)部功能以及內(nèi)部實現(xiàn)的理解。要求模擬采用二級目錄結(jié)構(gòu)的磁盤文件系統(tǒng)的文件操作能實現(xiàn)以下幾條命令,用輸入命令來模擬用戶程序中調(diào)用的文件操作:
Login 用戶登錄 Dir 列文件目錄(列出文件名、物理地址、保護碼和文件長度) Create 創(chuàng)建文件 Delete 刪除文件 Open 打開文件 Close 關(guān)閉文件 Read 讀文件 Write 寫文件 源文件可以進行讀寫保護
2、實驗原理
文件系統(tǒng)管理中用到的數(shù)據(jù)結(jié)構(gòu)有:
首先應(yīng)確定文件系統(tǒng)的數(shù)據(jù)結(jié)構(gòu):主目錄、子目錄及活動文件等。主目錄和子目錄都以文件的形式存放于磁盤,這樣便于查找和修改。 用戶創(chuàng)建的文件,可以編號存儲于磁盤上。如:file0,file1,file2…并以編號作為物理地址,在目錄中進行登記。
系統(tǒng)采用的開發(fā)環(huán)境
軟件:VC+ 6.0 操作系統(tǒng):Win 10
程序的流程圖




程序功能段的說明及代碼解釋
1.用戶注冊
void userCreate()
{
char c;
char userName[10];
int i;
if(used<MaxUser)
{
cout<<"Please input username:";
for(i=0;c=getch();i++)
{
if(c==13) break;
else
userName[i]=c;
printf("%c",c);
}
userName[i]='\0';
for(i=0;i<used;i++)
{
if(!strcmp(userTable[i].userName,userName))
{
cout<<"\n";
cout<<"該用戶名已存在,創(chuàng)建用戶失敗!\n";
system("pause");
return;
}
}
strcpy(userTable[used].userName,userName);
cout<<"\n";
cout<<"Please inout code:";
for(i=0;c=getch();i++)
{
if(c==13) break;
else
userTable[used].password[i]=c;
printf("*");
}
userTable[userID].password[i]='\0';
cout<<"\n";
cout<<"用戶創(chuàng)建成功!\n";
used++;
system("pause");
}
else
{
cout<<"創(chuàng)建用戶失敗,用戶已達到上限!\n";
system("pause");
}
fflush(stdin);// 清除讀寫緩沖區(qū)
}

用戶登錄
int login()
{
char name[10],psw[10];
char c;
int i,times;
cout<<"Please input username:";
for(i=0;c=getch();i++)
{
if(c==13) break;
else
name[i]=c;
printf("%c",c);
}
name[i]='\0';
for(i=0;i<used;i++)
{
if(!strcmp(userTable[i].userName,name))
break;
}
if(i==used)
{
cout<<"\n您輸入的用戶名不存在\n";
system("pause");
return -1;
}
for(times=0;times<3;times++)
{
memset(psw,'\0',sizeof(psw));
cout<<"\nPlease input code:";
for(i=0;c=getch();i++)
{
if(c==13) break;
else
psw[i]=c;
cout<<"*";
}
printf("\n");
for(i=0;i<used;i++)
{
if(!strcmp(psw,userTable[i].password))
{
printf("用戶登錄成功\n");
system("pause");
break;
}
}
if(i==used)
{
printf("您輸入的密碼錯誤,您還有%d次輸入機會\n",2-times);
if(times==2) exit(0);
}
else break;
}
fflush(stdin);
return i;
}

3.創(chuàng)建新文件
void createFile(char fileName[],int length,char fileKind[])
{
//int i,j;
time_t rawtime;
int startPos;
UFD *fileNode,*p;
for(p=userTable[userID].user->next;p!=NULL;p=p->next)
{
if(!strcmp(p->file->fileName,fileName))
{
printf("文件重名,創(chuàng)建文件失敗\n");
system("pause");
return;
}
}
if(requestDist(startPos,length)) //磁盤分配查詢
{
fileNode=(UFD *)malloc(sizeof(UFD));
fileNode->file=(fileTable *)malloc(sizeof(fileTable)); //這一步必不可少,因為fileNode里面的指針也需要申請地址,否則fileNode->file指向會出錯
strcpy(fileNode->file->fileName,fileName);
strcpy(fileNode->file->fileKind,fileKind);
fileNode->file->maxlength=length;
fileNode->file->strat=startPos;
fileNode->file->openFlag=false;
time(&rawtime);
fileNode->file->timeinfo=localtime(&rawtime);
fileNode->next=NULL;
if(userTable[userID].user->next==NULL)
userTable[userID].user->next=fileNode;
else
{
p=userTable[userID].user->next;
while(p->next) p=p->next;
p->next=fileNode;
}
printf("創(chuàng)建文件成功\n");
system("pause");
}
else
{
printf("磁盤空間已滿或所創(chuàng)建文件超出磁盤空閑容量,磁盤空間分配失敗\n");
system("pause");
}
}

4.文件寫入
void fileWrite(char fileName[])
{
UFD *p,*q;
q=userTable[userID].user;
int i,k,startPos;
for(p=q->next;p!=NULL;p=p->next)
{
if(!strcmp(p->file->fileName,fileName))
break;
}
if(p)
{
if(!strcmp(p->file->fileKind,"r")) //判斷文件類型
{
printf("該文件是只讀文件,寫入失敗\n");
system("pause");
return;
}
char str[500];
printf("輸入文件內(nèi)容:\n");
gets(str);
startPos=p->file->strat;
p->file->openFlag=true; //文件打開標記
p->file->length=strlen(str);
if(p->file->length>p->file->maxlength)
{
printf("寫入字符串長度大于該文件的總長度,寫入失敗\n");
system("pause");
return;
}
for(i=startPos,k=0;k<(int)strlen(str);i++,k++)
disk[i]=str[k];
printf("文件寫入成功,請用close命令將該文件關(guān)閉\n");
system("pause");
}
else
{
printf("沒有找到該文件,請檢查輸入的文件名是否正確\n");
system("pause");
}
}

5.關(guān)閉文件
void fileClose(char fileName[])
{
UFD *p,*q;
q=userTable[userID].user;
for(p=q->next;p!=NULL;p=p->next)
{
if(!strcmp(p->file->fileName,fileName))
break;
}
if(p)
{
p->file->openFlag=false;
printf("%s文件已關(guān)閉\n",p->file->fileName);
system("pause");
}
else
{
printf("沒有找到該文件,請檢查輸入的文件名是否正確!\n");
system("pause");
}
}

6.查看文件內(nèi)容
void fileCat(char fileName[])
{
int startPos,length;
int k=0;
UFD *p,*q;
q=userTable[userID].user;
for(p=q->next;p!=NULL;p=p->next)
{
if(!strcmp(p->file->fileName,fileName))
break;
}
if(p)
{
startPos=p->file->strat;
length=p->file->length;
p->file->openFlag=true; //文件打開標記
for(int i=startPos;k<length;i++,k++)
{
if(i%50==0) printf("\n"); //一行大于50個字符換行
printf("%c",disk[i]);
}
printf("%s已被read進程打開,請用close命令將其關(guān)閉\n",p->file->fileName);
system("pause");
}
else
{
printf("沒有找到該文件,請檢查輸入的文件名是否正確\n");
system("pause");
}
}

7.讀取文件
void fileFine(char fileName[])
{
UFD *p,*q;
q=userTable[userID].user;
for(p=q->next;p!=NULL;p=p->next)
{
if(!strcmp(p->file->fileName,fileName))
break;
}
if(p)
{
printf("-------------------------------------------\n");
printf("名字:%s\n",p->file->fileName);
printf("長度:%d\n",p->file->maxlength);
printf("起始地址:%d\n",p->file->strat);
printf("類型:%s\n",p->file->fileKind);
system("pause");
}
else
{
printf("沒有找到該文件,請檢查輸入的文件名是否正確\n");
system("pause");
}
}

8.顯示用戶所有文件
void fileDir(char userName[])
{
UFD *p;
int i,k;
for(i=0;i<MaxUser;i++)
{
if(!strcmp(userTable[i].userName,userName))
{
k=i;break;
}
}
if(i==MaxUser)
{
printf("沒有找到該用戶,請檢查輸入用戶名是否正確\n");
system("pause");
return;
}
else
{
p=userTable[k].user->next;
printf("----------------------------------------------------------\n");
cout<<setw(10)<<"文件名稱"<<setw(10)<<"文件長度"<<setw(10)<<"起始地址"<<setw(10)<<"文件類型"<<setw(30)<<"創(chuàng)建時間"<<endl;
for(;p!=NULL;p=p->next)
cout<<setw(10)<<p->file->fileName<<setw(10)<<p->file->maxlength<<setw(10)<<p->file->strat<<setw(10)<<p->file->fileKind<<setw(30)<<asctime(p->file->timeinfo)<<endl;
system("pause");
}
}

9.修改文件權(quán)限
void chmod(char fileName[],char kind[])
{
UFD *p,*q;
q=userTable[userID].user;
for(p=q->next;p!=NULL;p=p->next)
{
if(!strcmp(p->file->fileName,fileName))
break;
}
if(p)
{
strcpy(p->file->fileKind,kind);
cout<<"權(quán)限修改成功!"<<endl;
system("pause");
}
else
{
printf("沒有找到該文件,請檢查輸入的文件名是否正確\n");
system("pause");
}
}

10.重名名文件
void fileRen(char fileName[],char rename[])
{
UFD *p,*q;
q=userTable[userID].user;
for(p=q->next;p!=NULL;p=p->next)
{
if(!strcmp(p->file->fileName,fileName))
break;
}
if(p)
{
strcpy(p->file->fileName,rename);
cout<<"重命名成功!"<<endl;
system("pause");
}
else
{
printf("沒有找到該文件,請檢查輸入的文件名是否正確\n");
system("pause");
}
}

11.盤符顯示
void diskShow()
{
diskNode *p;
int i=0,unusedDisk=0;
printf("-------------------------------------------------------------------\n");
cout<<setw(10)<<"盤塊號"<<setw(10)<<"起始地址"<<setw(10)<<"容量(bit)"<<setw(30)<<"是否已被使用(1:是 0:否)"<<endl;
for(p=diskHead;p!=NULL;p=p->next,i++)
{
if(p->useFlag==false) unusedDisk+=p->maxlength;
cout<<setw(10)<<i<<setw(10)<<p->start<<setw(10)<<p->maxlength<<setw(30)<<p->useFlag<<endl;
}
cout<<"磁盤空間總?cè)萘?512*1024 bit "<<endl;
cout<<"已使用:"<<MaxDisk-unusedDisk<<" bit"<<endl;
cout<<"末使用:"<<unusedDisk<<" bit"<<endl;
system("pause");
}

12.刪除文件
void delFile(char fileName[])
{
UFD *p,*q,*temp;
while(p)
{
if(!strcmp(p->file->fileName,fileName)) break;//文件不存在
else
{
p=p->next;
q=q->next;
}
}
if(p)
{
if(p->file->openFlag!=true) //先判斷是否有進程打開該文件,如果文件沒被打開
{
temp=p;
free(temp);
printf("文件刪除成功\n");
system("pause");
}
else
{
printf("該文件已被進程打開,刪除失敗\n");//文件被打開
system("pause");
}
}
else
{
system("pause");
}
}

13.顯示所有用戶
void show_allusers()
{
if(used==0)
{
cout<<"暫無用戶!"<<endl;
}
else
{
cout<<setw(10)<<"用戶名"<<setw(10)<<"密碼"<<endl;
for(int i=0;i<used;i++)
{
cout<<setw(10)<<userTable[i].userName<<setw(10)<<"******"<<endl;
}
}
system("pause");
}

課程設(shè)計體會與軟件評價
通過這次的操作系統(tǒng)課程設(shè)計,自己也學(xué)到了非常多的新知識,同時也對以前的一些知識復(fù)習(xí)了一些。拿到課設(shè)題目的時候,還是有點懵的,后面選擇了文件系統(tǒng)這道題,因為這方面一直都是自己的薄弱地方,想突破一下自己。
和以往做課程設(shè)計一樣,拿到題目,首先在網(wǎng)上收集相關(guān)的資料,學(xué)習(xí)別人的思路和見解。然后在根據(jù)自己的理解和思考,確定程序所需要實現(xiàn)的功能模塊。起初在搭建框架的時候,陷入了困難,因為不知道文件系統(tǒng)到達是怎么實現(xiàn)的?用戶是怎么創(chuàng)建目錄、文件?對于這個疑惑,咨詢了一下同學(xué),之后又去找了文件系統(tǒng)的書看了一下,這才了解文件系統(tǒng)的大體結(jié)構(gòu)。之后就是確定程序的流程,采用哪種輸入方法。
起初想著還是和以前一樣,用戶選擇命令前面的數(shù)字,系統(tǒng)根據(jù)命令變換確定用戶所需要執(zhí)行的命令。后來想著這和平時使用的Linux系統(tǒng)操作方法完全不一樣啊,命令行操作方便又快捷,為何不寫一個類似的程序呢?用戶直接使用命令操作文件,這樣才比較符合用戶的操作習(xí)慣。為此,自己又拿起C++的課本重新學(xué)了一遍文件操作、指針等知識。之后用了一點時間搭建了整個程序的主體框架,然后只需要對每個模塊進行填充就好了,這里不是很難。
在課設(shè)中,遇到的問題數(shù)不勝數(shù)。比如主目錄、二級目錄的數(shù)據(jù)結(jié)構(gòu)怎么設(shè)計?鏈表的一些基礎(chǔ)操作方式如何選擇等等。好在同學(xué)們的幫助下,這才完成了文件系統(tǒng)設(shè)計。在使用自己設(shè)計的這個軟件,發(fā)現(xiàn)依然存在一些問題,比如在為文件定義操作權(quán)限的時候,這里并沒有對權(quán)限進行用戶限制,用戶是可以隨意定義權(quán)限的,這與實際相差比較大。總的來說,這次的收獲還是很大的,希望在以后的編程中可以寫出更優(yōu)秀的代碼。
這次的操作系統(tǒng)課程設(shè)計,雖然總體上完成了老師所給出的基本功能,添加了一點點新的功能,但是問題還是有很多。比如并沒有對文件進行真正的存儲,只是利用鏈表進行了存儲,導(dǎo)致一旦程序關(guān)閉,用戶數(shù)據(jù)就不見了。
其實在設(shè)計程序的時候也考慮過這個問題,但是對于文件的操作,一直都是自己的痛點,在C++的基礎(chǔ)課上,文件這一部分沒有學(xué)的很好,希望在以后的學(xué)習(xí)過程中,可以查缺補漏。其次就是程序的優(yōu)化并沒有做的很好,存在很多冗余的地方,代碼的優(yōu)化空間還是很大的??偨Y(jié)這次的程序,做的沒有以前的課設(shè)那么好,在用戶交互性方面還值得改進和提升。
源代碼
運行環(huán)境:VC 6.0(vs會報錯)
下載鏈接??:點擊下方“寫留言|查看留言”
進入留言板就可以查看
注:
因為有網(wǎng)站老是爬文章,所以把下載鏈接放在小程序中了 以前編寫代碼的時候 沒有設(shè)計到復(fù)制文本內(nèi)容 所以只有手動輸入了 若鏈接失效 麻煩留下言 提醒下 海轟看到會及時更新的
忙了幾個月了 沒有看到小伙伴們的留言、消息
看到了的基本都發(fā)了代碼
真的很抱歉 確實有點忙
之后會陸續(xù)整理課程設(shè)計源代碼的
不需要再用竹筍下載了
直接獲取就行了
小程序也會比較大的更新
工作量較大 見諒~

