在fs.h当中,定义了变量NR_OPEN
#define NR_OPEN20
在任务的task_struct(sched.h)结构体当中,有一项,如下:
struct file * filp[NR_OPEN];
即当前任务打开的文件列表,所以每个进程最多打开文件20个。
另外,0.11当中,最多打开文件数为64个:
#define NR_FILE64
extern struct file file_table[NR_FILE];
在0.11中,所有的对块设备的读写都是通过缓冲区进行的,当然,块设备驱动程序除外。在内存当中,高速缓冲区在内核模块后,主内存区域之前。
一般来说,1个块等于2个扇区,而扇区为512字节,现在随着大容量磁盘的应用,扇区逐渐的变大,现在有4k的扇区,磁盘的最小存储单位是扇区,数据存储的最小单位是块,块是对文件系统而言的。
高速缓冲区高位被划分为一个个缓冲区块,每个1024字节,在内核中,高速缓冲区通过hash_table寻块,在buffer.c当中定义:
struct buffer_head * hash_table[NR_HASH]= {0};
其中NR_HASH在fs.h当中定义:
#define NR_HASH 307
而在低位存放的是对应缓存区块的头结构这是一个双向链表,如下:
struct buffer_head
{
char *b_data; /* pointerto data block (1024 bytes) *///指针。
unsigned long b_blocknr; /* block number*/// 块号。
unsigned short b_dev; /* device (0 =free) */// 数据源的设备号。
unsigned char b_uptodate; // 更新标志:表示数据是否已更新。
unsigned char b_dirt; /* 0-clean,1-dirty*///修改标志:0 未修改,1 已修改.
unsigned char b_count; /* users usingthis block */// 使用的用户数。
unsigned char b_lock; /* 0 - ok, 1-locked */// 缓冲区是否被锁定。
struct task_struct*b_wait; // 指向等待该缓冲区解锁的任务。
struct buffer_head*b_prev; // hash 队列上前一块(这四个指针用于缓冲区的管理)。
struct buffer_head*b_next; // hash 队列上下一块。
struct buffer_head*b_prev_free; // 空闲表上前一块。
struct buffer_head *b_next_free; // 空闲表上下一块。
};
高速缓冲区位置,在main.c当中,根据内存大小的不同,高速缓冲区的大小也不同:
// 内存大小=1Mb 字节+扩展内存(k)*1024 字节。
memory_end = (1<<20) + (EXT_MEM_K<<10);
memory_end &= 0xfffff000; // 忽略不到Kb(页)的内存数。
if (memory_end> 16*1024*1024) // 如果内存超过Mb,则按Mb 计。
memory_end= 16*1024*1024;
// 如果内存>12Mb,则设置缓冲区末端=4Mb
if (memory_end> 12*1024*1024)
buffer_memory_end= 4*1024*1024;
// 否则如果内存>6Mb,则设置缓冲区末端=2Mb
else if (memory_end > 6*1024*1024)
buffer_memory_end= 2*1024*1024;
else
buffer_memory_end= 1*1024*1024;// 否则则设置缓冲区末端=1Mb
main_memory_start= buffer_memory_end;//主内存起始位置=缓冲区末端;
如果内存打印12M,则设置高速缓冲区末尾在4M的位置,如果<=12M 且>6M,高速缓冲区末尾为2M,如果<=6M,高速缓冲区为1M。
而640k-1M之间是显卡,BIOS缓存区域,所以如果内存<6M ,那么高速缓冲区的高端地址就是640K,那么缓冲区块从640k往下划分。如果高速缓冲区末尾不为1M,则从末尾开始分块,从开头开始写入buffer_head:
void buffer_init(long buffer_end)
{
//start_buffer是内核模块的末端,是由ld链接产生的
structbuffer_head * h = start_buffer;
void* b;
int i;
if (buffer_end== 1<<20)
b= (void *) (640*1024);
else
b= (void *) buffer_end;
while ( (b-= BLOCK_SIZE) >= ((void *) (h+1)) ) {
h->b_dev = 0;
h->b_dirt = 0;
h->b_count = 0;
h->b_lock = 0;
h->b_uptodate= 0;
h->b_wait= NULL;
h->b_next= NULL;
h->b_prev= NULL;
h->b_data= (char *) b;
h->b_prev_free= h-1;
h->b_next_free= h+1;
h++;
NR_BUFFERS++; //缓冲区块计数
if(b == (void *) 0x100000) //b分块到1M位置结束
b= (void *) 0xA0000;
}
h--;
//设置空闲缓冲区列表
free_list= start_buffer;
free_list->b_prev_free= h;
h->b_next_free= free_list;
for (i=0;i<NR_HASH;i++)
hash_table[i]=NULL;
}