scanzone(zp, ind, len, fn)
参数的含义 zp 逻辑块号,
ind=0,1,2,0代表直接块,1代表1次间接块,2代表2次间接块。
len代表每个块里面有几个i节点的个数,这里应该是32
fn是个函数指针 fn = (INODEFN) readshoe)
inode_nr
scanzone F4(zone_nr *, zp, int, level, int, n, INODEFN, fn)
{
long b; /* current block */
int i; /* index */
inode_nr v; /* return value from function */
buffer tb; /* zone reading buffer */
do {
b = zoneblock(*zp++);
i = zsize;
do {
readblock(b++, (buffer *) &tb[0]);
if ((v = level ? scanzone((zone_nr *) tb, level-1,
sizeof(tb)/sizeof(zone_nr), fn)
: (*fn)(tb)) != 0)
goto DoneScan;
} while (--i);
} while (--n);
DoneScan:
return v;
}
外循环的递减n,内循环递减i,
i = zsize;
zsize在shoeboot.c里面定义
zsize = 1 << ((struct super_block *) blockbuf)->s_log_zone_size;
所以zsize为1。因此,里面的循环可以把do{...}while(--i)去掉。
if ((v = level ? scanzone((zone_nr *) tb, level-1,
sizeof(tb)/sizeof(zone_nr), fn)
: (*fn)(tb)) != 0)
goto DoneScan;
含义是:如果是直接块,则level为0,则调用(*fn)(tb))
如果是间接块,则,level为1或2,则递归调用scanzone()函数。
sizeof(tb)/sizeof(zone_nr)这里不正确,因为zone_nr为指针类型,占4个字节。
现在是实模式,所以sizeof(zone_nr),占两个字节。
应该改为sizeof(tb)/2,因为minix-1.0文件系统的块号为2个字节表示。
当然因为shoelace不大,这里为47.1k所以需要7个直接块,
1个间接块,这个间接块里需要41个直接块号。
而sizeof(tb)/sizeof(zone_nr)为256,所以不会出现错误。
readblock()函数作用读取一个块到缓冲区中。
readshoe()函数作用是把缓冲区里面的内容拷贝到内存的bufptr开始的连续的区域。
bootlace.x里面有startload的定义为1
_startload: .byte 1
static inode_nr
readshoe F1(buffer *, bp)
{
unsigned int hsize; /* size of a.out header */
hsize = 0;
if (startload != 0)
hsize = ((struct exec *) bp)->a_hdrlen;
startload = 0;
copyviabufptr((char *) bp + hsize, sizeof(*bp)-hsize); //第一次拷贝不要拷贝文件头部
filesize -= sizeof(*bp);
hsize = 0;
if (checkfilesize() <= 0)
hsize = 2*ROOT_INODE;
return hsize;
}
下面是copyviabufptr()函数分析
bufptr的初始化是个问题,在这里:
mov ax,#BOOTSEG | work out 32 bit address
mul _hclicksize
mov _bufptr+0,ax
mov _bufptr+2,dx
BOOTSEG = 0x1000 |here it will copy itself (64k-127k)
难道是巧合?shoelace被加载到了0x10000
而linux-0.11的system也被加载到了0x10000