MIT6.828_HW11_xv6 log

2024-01-11 02:18
文章标签 log xv6 mit6.828 hw11

本文主要是介绍MIT6.828_HW11_xv6 log,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

MIT6.828_HW11_xv6 log

First, you’ll artificially create a crash which illustrates why logging is needed. Second, you’ll remove one inefficiency in the xv6 logging system.

1.1. Creating a Problem

xv6日志的要点是使所有可能产生崩溃的文件系统操作都是原子的。 例如,文件创建涉及向目录添加新条目以及将新文件的inode标记为使用中。 如果没有日志,则在重新启动后,在一个之后但在另一个之前发生的崩溃将使文件系统处于不正确的状态。

First, replace commit() in log.c with this code:

#include "mmu.h"
#include "proc.h"
void
commit(void)
{int pid = myproc()->pid;if (log.lh.n > 0) {write_log();write_head();if(pid > 1)            // AAAlog.lh.block[0] = 0; // BBB// Copy committed blocks from log to their home locationinstall_trans();if(pid > 1)            // AAApanic("commit mimicking crash"); // CCClog.lh.n = 0; write_head();}
}

BBB行导致日志中的第一个块被写入 0,而不是写入应该写入的任何位置。 在文件创建期间,日志中的第一个块是新文件已更新为非零类型的inode。 行BBB使具有更新的inode的块被写入 0(从而永远不会被读取),使得磁盘上的inode仍然标记为未分配。 CCC行强制一次崩溃。 AAA行抑制了init的这种错误行为,它在shell启动之前创建文件。

log结构体定义。

struct log {struct spinlock lock;int start;int size;int outstanding; // how many FS sys calls are executing.int committing;  // in commit(), please wait.int dev;struct logheader lh;
};// Contents of the header block, used for both the on-disk header block
// and to keep track in memory of logged block# before commit.
struct logheader {int n;int block[LOGSIZE];
};

Second, replace recover_from_log() in log.c with this code:

此修改会抑制日志恢复(这本能修复因更改commit()而导致的 damage)。

Finally, remove the -snapshot option from the definition of QEMUEXTRA in your Makefile so that the disk image will see the changes.

$ echo hi>a
lapicid 0: panic: commit mimicking crash80102dc3 80105292 80104987 80105b89 8010587c 0 0 0 0 0$ cat a 
lapicid 0: panic: ilock: no type80101837 801051d8 80104977 80105b79 8010586c 0 0 0 0 0

我们应该明白为什么会出现这种现象。哪部分文件创建的修改在崩溃发生之前被写入了磁盘,哪部分没有。block[0]写入了全零,log.lh.n = 0;没有写入。此时OS认为该文件还有缓冲区的内容没有写入,同时因为其 type 修改成了零(block[0] = 0),就出现了 no type的 panic.

1.2. Solving the Problem

fix recover_from_log()

static void
recover_from_log(void)
{read_head();cprintf("recovery: n=%d\n", log.lh.n);install_trans();log.lh.n = 0;write_head();
}

此时不会出现 panic, 但尽管执行了echo hi>a,a文件依旧是一个空文件。因为再次启动OS时, 缓冲区的内容已经丢失了,install_trans操作并没有实际写入内容。这里也反映出必须保证文件操作的原子性。

怀着好奇心,我进行了又一步骚操作。但是不知道为什么,在我们实验修改了install_trans(即直接从缓冲区将数据写入物理内存)之后,按照之前的操作,会出现no type的 panic。讲道理应该是没有影响的啊。

recovery: n=2 but ignoring
init: starting sh
$ cat a
$

1.3. Streamlining Commit

这一部分要分清几个概念。commitend_op中调用。

  • 缓冲区, log.lh.block: 定义在log结构体中,OS直接修改的内容。
  • 物理块: 当OS对某一块的内容进行修改后,缓冲区的内容就会与物理块的内容不同。物理块真正存在于磁盘中。
  • log 块, log.start: 记录缓冲区内容的变换,log.start 记录了修改内容的地址。

假设文件系统代码想要更新块33中的一个 inode。文件系统代码将调用bp = bread(block 33)并且更新缓冲区中的数据。commit()中的write_log()将会把缓冲区的数据拷贝到 log 块,例如块3。install_trans()读块3,拷贝块3的内容到块33的内存缓冲区,最后将内容写到块33中。

**Since the modified block 33 is guaranteed to already be in the buffer cache, there’s no need for install_trans() to read block 33 from the log. **其实我们可以不必从log中读数据,我们可以直接将缓冲区的数据写到块33就可以了。

修改install_trans如下。

static void
install_trans(void)
{int tail;for (tail = 0; tail < log.lh.n; tail++) {// struct buf *lbuf = bread(log.dev, log.start+tail+1); // read log blockstruct buf *dbuf = bread(log.dev, log.lh.block[tail]); // read dst// memmove(dbuf->data, lbuf->data, BSIZE);  // copy block to dstbwrite(dbuf);  // write dst to disk// brelse(lbuf);brelse(dbuf);}
}

到最后,我们可以仔细体会一下这个HW。首先,这个HW让我们体会到了文件操作需要满足原子性,不然十分容易导致文件系统产生错误。log 机制实现了 OS对文件的操作(对 log 缓冲区的操作),最后通过commit 将修改写入物理内存,这避免了频繁地访问磁盘,可以提高文件操作地速度。 最后,我们发现可以直接将缓冲区的数据写入物理内存,可以优化数据存取的速度!

这篇关于MIT6.828_HW11_xv6 log的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/592826

相关文章

内核启动时减少log的方式

内核引导选项 内核引导选项大体上可以分为两类:一类与设备无关、另一类与设备有关。与设备有关的引导选项多如牛毛,需要你自己阅读内核中的相应驱动程序源码以获取其能够接受的引导选项。比如,如果你想知道可以向 AHA1542 SCSI 驱动程序传递哪些引导选项,那么就查看 drivers/scsi/aha1542.c 文件,一般在前面 100 行注释里就可以找到所接受的引导选项说明。大多数选项是通过"_

ImportError: cannot import name ‘print_log‘ from ‘logging‘

mmcv升级到2.+后删除了很多 解决 查FAQ文档,找到 添加到mmcv.utils下即可

DAY16:什么是慢查询,导致的原因,优化方法 | undo log、redo log、binlog的用处 | MySQL有哪些锁

目录 什么是慢查询,导致的原因,优化方法 undo log、redo log、binlog的用处  MySQL有哪些锁   什么是慢查询,导致的原因,优化方法 数据库查询的执行时间超过指定的超时时间时,就被称为慢查询。 导致的原因: 查询语句比较复杂:查询涉及多个表,包含复杂的连接和子查询,可能导致执行时间较长。查询数据量大:当查询的数据量庞大时,即使查询本身并不复杂,也可能导致

多数据源的事务处理总是打印很多无用的log日志

之前做了一个项目,需要用到多数据源以及事务处理,在使用事务处理,服务器总是打印很多关于事务处理的log日志(com.atomikos.logging.Slf4jLogger),但是我们根本不会用到这些log日志,反而使得查询一些有用的log日志变得困难。那要如何屏蔽这些log日志呢? 之前的项目是提高项目打印log日志的级别,后来觉得这样治标不治本。 现在有一个更好的方法: 我使用的是log

log file sync等待事件

概念: 1、REDO组件: redolog buffer=>位于SGA中,是一块循环使用的内存区域,保存数据库变更的相关信息并以重做条目redoentries形式存储,包含DML及DDL语句; LGWR=>通过此进程把redo buffer的内容写到redo log file中; redo log file=>(在归档模式下被ARC n最终写入归档日志)。最少两组重做日志,每组最少

git 学习的流水log

git命令联系 配置以及修改全局user信息 git config --global user.name 'you_name' git config --global user.email 'you_email@qq.com' 现有设备中的所有配置 git config --list 现有设备中的所有配置 git config --list --local/--global/--syste

Android串口log的获取

常遇到无法开机的状况,这时由于Android还未起来,adb等均无法使用,此时有抓串口的必要。 1.命令安装 sudo apt-get updatesudo apt-get install minicom 2.安装完毕后,插入串口线,进入/dev/目录查看设备 图中红圈即插入串口后,新增的serial目录和ttyUSB0字符设备 其中serial目录中内容如下,均是指

android log输出行位置和方法名 以及导出jar包

android log 输出行位置和方法名 public class DebugInfo extends Exception {public int line() {StackTraceElement[] trace = getStackTrace();if (trace == null || trace.length == 0) {return -1;}return trace[0].get

php记录自定义log日志方法

php记录log日志方法: /*** 记录错误日志* @param 日志内容 $res*/function save_log($res) {$err_date = date("Ym", time());//$address = '/var/log/error';$address = './error';if (!is_dir($address)) {mkdir($address, 0700,

【面试八股总结】MySQL日志:undo log、redo log、binlog

MySQL中存在三种日志: undo log(回滚日志):是 Innodb 存储引擎层生成的日志,实现了事务中的原子性,主要用于事务回滚和 MVCC。redo log(重做日志):是 Innodb 存储引擎层生成的日志,实现了事务中的持久性,主要用于掉电等故障恢复;binlog (归档日志):是 Server 层生成的日志,主要用于数据备份和主从复制; 一、回滚日志undo log