這個應該是這個系列的尾聲了,一個完整的操做系統可能最主要的也就是分紅這幾大模塊:進程管理、內存管理和文件系統。計算機以進程爲基本單位進行資源的調度和分配;而與用戶的交互,基本單位則是文件node
文件正是對生磁盤的抽象git
一個磁盤由多個盤面串聯而成,而一個盤面又被分爲磁道,磁道又由扇區組成。github
磁盤的訪問單元就是扇區,一個扇區爲512字節算法
也就是向控制器發送柱面磁頭扇區等信息,而後等待迴應數組
盤塊是對扇區的抽象數據結構
程序負責提升盤塊block,而磁盤驅動負責從block計算出cyl,head,sec(CHS),最後傳遞到磁盤控制器上app
磁盤訪問時間 = 寫入控制器時間 + 尋道時間 + 旋轉時間 + 傳輸時間
ide
其中主要的時間都在尋道時間和旋轉時間,因此對扇區抽象成盤塊就能夠一次訪問多個扇區來節省磁盤的訪問時間函數
既然有多進程交替執行,就有可能多個進程同時訪問相同磁盤的狀況,就須要一個請求隊列來處理全部請求,就會涉及到調度算法了this
FCFS調度
FCFS是最公平最直觀的算法,也就是按照隊列順序來訪問磁盤,可是效率也很低下,磁頭會在不規律的磁道長途奔襲
SSTF調度
SSTF算法就相似短做業優先算法,先尋找更近距離的磁道,可是SSTF算法可能會產生飢餓問題,過長距離的磁道可能一直得不處處理
SCAN調度
SCAN算法就是SSTF算法的改良版,也就是進行SSTF,可是在中途不會折返去尋找更短距離的磁道,這樣就避免了飢餓問題
C-SCAN調度(電梯算法)
把掃描限定在一個方向,當訪問到某個方向的最後一個磁道時,磁道返回磁盤相反方向磁道的末端,並再次開始掃描。
文件是對磁盤的第三層抽象,扇區和盤塊分別是前兩層抽象。之因此有文件這層抽象是爲了方便用戶的使用,在用戶的眼裏,磁盤上的信息均可以看做是字符流。因此文件的抽象九能夠看做是字符流到盤塊集合的映射關係
從文件到盤塊的映射來看,通常有這幾種組織方式
記錄是定長的且按關鍵字順序排列。能夠順序存儲或以鏈表形勢存儲,在訪問時須要順序搜索文件。順序文件有如下兩種結構:
第一種是串結構,各記錄之間的順序與關鍵字無關。一般的辦法是由時間來決定,即按存入時間的前後排列,最早存入的記錄做爲第一個記錄,其次存入的爲第二個記錄,以此類推。
第二種是順序結構,指文件中全部記錄按關鍵字順序排列。 在對記錄進行批量操做時,即每次要讀或寫一大批記錄,對順序文件的效率是全部邏輯文件中最高的;此外,也只有順序文件才能存儲在磁帶上,並能有效的工做。但順序文件對查找、修改、增長或刪除單個記錄的操做比較困難。
對於可變長記錄的文件只能順序查找,系統開銷較大,爲此能夠創建一張索引表以加快檢索速度,索引表自己是順序文件。在記錄不少或是訪問要求高的文件中,須要引入索引以提供有效的訪問,實際中,經過索引能夠成百上千倍的提升訪問速度。
索引順序表是順序和索引兩種組織形勢的結合。索引順序文件將順序文件中全部記錄分爲若干個組,爲順序文件創建一張索引表,在索引表中爲每組中的第一個記錄創建一個索引項,其中含有該記錄的關鍵字值和指向該記錄的指針。
在實際的操做系統實現中,通常是採用多級索引
文件系統或者說目錄是對磁盤的第四個抽象,也就是抽象了整個磁盤
操做系統爲了實現文件目錄,引入了稱爲文件控制塊的數據結構。
文件控制塊(FCB)是用來存放控制文件須要的各類信息的數據結構,以實現「按名存取」。FCB的有序集合稱爲文件目錄,一個FCB就是一個文件目錄項。爲了建立一個新文件,系統將分配一個FCB並存放在文件目錄中,稱爲目錄項。
FCB主要包含如下信息:
在多級目錄下通常對磁盤就能夠抽象爲
FCB數組
FCB數組就是將全部盤塊的FCB信息都集中到一個數組中
數據盤塊集合
在每一個數據盤塊裏都包含一些目錄項用來找到子目錄,目錄項也就是文件名+對應的FCB的「地址」,也就是去以前的FCB數組中找到相應的FCB
在磁盤進行格式化的時候,會存放一些信息用來知道一些磁盤信息和找到根目錄
inode位圖: 哪些inode空閒,哪些被佔用
超級塊:記錄兩個位圖有多大等信息
盤塊位圖: 哪些盤塊是空閒的,硬盤大小不一樣這個位圖的大小也不一樣
在我以前實現的FragileOS裏文件系統很是簡陋,基本沒有什麼好說的。這其實也是爲何以前把這個系列改了一個方向來結合的看Linux0.11的代碼。因此來看一下Linux0.11裏是怎麼使用和實現文件系統的,
int sys_read(unsigned int fd,char * buf,int count) {
struct file * file;
struct m_inode * inode;
if (fd>=NR_OPEN || count<0 || !(file=current->filp[fd]))
return -EINVAL;
if (!count)
return 0;
verify_area(buf,count);
inode = file->f_inode;
if (inode->i_pipe)
return (file->f_mode&1)?read_pipe(inode,buf,count):-EIO;
if (S_ISCHR(inode->i_mode))
return rw_char(READ,inode->i_zone[0],buf,count,&file->f_pos);
if (S_ISBLK(inode->i_mode))
return block_read(inode->i_zone[0],&file->f_pos,buf,count);
if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode)) {
if (count+file->f_pos > inode->i_size)
count = inode->i_size - file->f_pos;
if (count<=0)
return 0;
return file_read(inode,file,buf,count);
}
printk("(Read)inode->i_mode=%06o\n\r",inode->i_mode);
return -EINVAL;
}
複製代碼
int file_read(struct m_inode * inode, struct file * filp, char * buf, int count) {
int left,chars,nr;
struct buffer_head * bh;
if ((left=count)<=0)
return 0;
while (left) {
if ((nr = bmap(inode,(filp->f_pos)/BLOCK_SIZE))) {
if (!(bh=bread(inode->i_dev,nr)))
break;
} else
bh = NULL;
nr = filp->f_pos % BLOCK_SIZE;
chars = MIN( BLOCK_SIZE-nr , left );
filp->f_pos += chars;
left -= chars;
if (bh) {
char * p = nr + bh->b_data;
while (chars-->0)
put_fs_byte(*(p++),buf++);
brelse(bh);
} else {
while (chars-->0)
put_fs_byte(0,buf++);
}
}
inode->i_atime = CURRENT_TIME;
return (count-left)?(count-left):-ERROR;
}
複製代碼
int file_write(struct m_inode * inode, struct file * filp, char * buf, int count) {
off_t pos;
int block,c;
struct buffer_head * bh;
char * p;
int i=0;
/* * ok, append may not work when many processes are writing at the same time * but so what. That way leads to madness anyway. */
if (filp->f_flags & O_APPEND)
pos = inode->i_size;
else
pos = filp->f_pos;
while (i<count) {
if (!(block = create_block(inode,pos/BLOCK_SIZE)))
break;
if (!(bh=bread(inode->i_dev,block)))
break;
c = pos % BLOCK_SIZE;
p = c + bh->b_data;
bh->b_dirt = 1;
c = BLOCK_SIZE-c;
if (c > count-i) c = count-i;
pos += c;
if (pos > inode->i_size) {
inode->i_size = pos;
inode->i_dirt = 1;
}
i += c;
while (c-->0)
*(p++) = get_fs_byte(buf++);
brelse(bh);
}
inode->i_mtime = CURRENT_TIME;
if (!(filp->f_flags & O_APPEND)) {
filp->f_pos = pos;
inode->i_ctime = CURRENT_TIME;
}
return (i?i:-1);
}
複製代碼
int sys_open(const char * filename,int flag,int mode) {
struct m_inode * inode;
struct file * f;
int i,fd;
mode &= 0777 & ~current->umask;
for(fd=0 ; fd<NR_OPEN ; fd++)
if (!current->filp[fd])
break;
if (fd>=NR_OPEN)
return -EINVAL;
current->close_on_exec &= ~(1<<fd);
f=0+file_table;
for (i=0 ; i<NR_FILE ; i++,f++)
if (!f->f_count) break;
if (i>=NR_FILE)
return -EINVAL;
(current->filp[fd]=f)->f_count++;
if ((i=open_namei(filename,flag,mode,&inode))<0) {
current->filp[fd]=NULL;
f->f_count=0;
return i;
}
/* ttys are somewhat special (ttyxx major==4, tty major==5) */
if (S_ISCHR(inode->i_mode)) {
if (MAJOR(inode->i_zone[0])==4) {
if (current->leader && current->tty<0) {
current->tty = MINOR(inode->i_zone[0]);
tty_table[current->tty].pgrp = current->pgrp;
}
} else if (MAJOR(inode->i_zone[0])==5)
if (current->tty<0) {
iput(inode);
current->filp[fd]=NULL;
f->f_count=0;
return -EPERM;
}
}
/* Likewise with block-devices: check for floppy_change */
if (S_ISBLK(inode->i_mode))
check_disk_change(inode->i_zone[0]);
f->f_mode = inode->i_mode;
f->f_flags = flag;
f->f_count = 1;
f->f_inode = inode;
f->f_pos = 0;
return (fd);
}
複製代碼
static struct m_inode * get_dir(const char * pathname) {
char c;
const char * thisname;
struct m_inode * inode;
struct buffer_head * bh;
int namelen,inr,idev;
struct dir_entry * de;
if (!current->root || !current->root->i_count)
panic("No root inode");
if (!current->pwd || !current->pwd->i_count)
panic("No cwd inode");
if ((c=get_fs_byte(pathname))=='/') {
inode = current->root;
pathname++;
} else if (c)
inode = current->pwd;
else
return NULL; /* empty name is bad */
inode->i_count++;
while (1) {
thisname = pathname;
if (!S_ISDIR(inode->i_mode) || !permission(inode,MAY_EXEC)) {
iput(inode);
return NULL;
}
for(namelen=0;(c=get_fs_byte(pathname++))&&(c!='/');namelen++)
/* nothing */ ;
if (!c)
return inode;
if (!(bh = find_entry(&inode,thisname,namelen,&de))) {
iput(inode);
return NULL;
}
inr = de->inode;
idev = inode->i_dev;
brelse(bh);
iput(inode);
if (!(inode = iget(idev,inr)))
return NULL;
}
}
複製代碼