指针类型强制转化在kernel设计中非常常见,这里记录两个非常有意思的用法:
1、对地址进行运算。任何虚拟地址都表示成void *va = (void *) 100, *(va + 1) ==101,表示虚拟地址va的下一个虚拟地址,但在查找PageTable的时候,首选把它转化成数字(uint32_t) (va) ,然后取这个32位数的前10位用来查找page directory (uint32_t) (va) >>22
2、磁盘中一个块表示为
struct buf{
int flags;
char data[512];
struct buf *prev;
struct buf *next;
int blockno;
int dev;
} ;
为了避免wirte crash,在写快的时候只把那个快的blockno写到日志文件的loghead中,当一堆写文件的系统调用结束后,把log head写入到磁盘,如果写入成功,表示commit()成功,开始真正的块写入
struct logheader {
int n; //n表示有多少个block需要写到disk中
int block[30];//每个元素记录了需要写到disk中的blockno
};
问题来了,假设我要写入3个快,blockno 是1,2,3,logheader 的block[30] = {1,2,3},那如何把logheader写入到磁盘的log.dev设备的快号为 log.start的物理块?方法是把整个logheader结构体映射到buf中的data,
struct buf *buf = bread(log.dev, log.start); //加载要写入的磁盘的位置
struct logheader *hb = (struct logheader *) (buf->data);
int i;
hb->n = log.lh.n;
for (i = 0; i < log.lh.n; i++) {
hb->block[i] = log.lh.block[i];
}
bwrite(buf);
brelse(buf);
上面对hb的修改实际上都是对buf->data的修改