# 15.4 log\_write函数

接下来让我们看一些代码来帮助我们理解这里是怎么工作的。前面我提过事务（transaction），也就是我们不应该在所有的写操作完成之前写入commit record。这意味着文件系统操作必须表明事务的开始和结束。在XV6中，以创建文件的sys\_open为例（在sysfile.c文件中）每个文件系统操作，都有begin\_op和end\_op分别表示事物的开始和结束。

![](/files/-MS_NMysPF-mY9gV-y6e)

begin\_op表明想要开始一个事务，在最后有end\_op表示事务的结束。并且事务中的所有写block操作具备原子性，这意味着这些写block操作要么全写入，要么全不写入。XV6中的文件系统调用都有这样的结构，最开始是begin\_op，之后是实现系统调用的代码，最后是end\_op。在end\_op中会实现commit操作。

在begin\_op和end\_op之间，磁盘上或者内存中的数据结构会更新。但是在end\_op之前，并不会有实际的改变（注，也就是不会写入到实际的block中）。在end\_op时，我们会将数据写入到log中，之后再写入commit record或者log header。这里有趣的是，当文件系统调用执行写磁盘时会发生什么？

让我们看一下fs.c中的ialloc，

![](/files/-MS_PHSEoZWSt888RY7q)

在这个函数中，并没有直接调用bwrite，这里实际调用的是log\_write函数。log\_write是由文件系统的logging实现的方法。任何一个文件系统调用的begin\_op和end\_op之间的写操作总是会走到log\_write。log\_write函数位于log.c文件，

![](/files/-MS_QF-YFBCY37u8H-q0)

log\_write还是很简单直观的，我们已经向block cache中的某个block写入了数据。比如写block 45，我们已经更新了block cache中的block 45。接下来我们需要在内存中记录，在稍后的commit中，要将block 45写入到磁盘的log中。

这里的代码先获取log header的锁，之后再更新log header。首先代码会查看block 45是否已经被log记录了。如果是的话，其实不用做任何事情，因为block 45已经会被写入了。这种忽略的行为称为log absorbtion。如果block 45不在需要写入到磁盘中的block列表中，接下来会对n加1，并将block 45记录在列表的最后。之后，这里会通过调用bpin函数将block 45固定在block cache中，我们稍后会介绍为什么要这么做（注，详见15.8）。

以上就是log\_write的全部工作了。任何文件系统调用，如果需要更新block或者说更新block cache中的block，都会将block编号加在这个内存数据中（注，也就是log header在内存中的cache），除非编号已经存在。

> 学生提问：这是不是意味着，bwrite不能直接使用？
>
> Frans教授：是的，可以这么认为，文件系统中的所有bwrite都需要被log\_write替换。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mit-public-courses-cn-translatio.gitbook.io/mit6-s081/lec15-crash-recovery-frans/15.4-log-write-han-shu.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
