本文重在讲述filefile_header的联系与区别,首先分别分析了filefile_header结构体,而后介绍两者的联系,最后分析几组易混的成员变量,包括pagelog_pagefilefile_headerflagsdeprecated_eof_hintendrecord_countlog_records

1. file

结构体file源码如下:

struct file
{
  cfs_offset_t end;
  coffee_page_t page;
  coffee_page_t max_pages;
  int16_t record_count;
  uint8_t references;
  uint8_t flags;
};

end

指向存放文件的最后一个字节的偏移量,当打开一个文件时,Coffee用蛮力法找到文件末尾(file_header是不存储文件末尾的位置,因为文件长度经常改变)。详情见博文《打开文件cfs_open》。

page

指向物理文件的第一页,即存放文件元数据file_header的页。通常的用法如下:

//用法1:static struct file *find_file(const char *name)
read_header(&hdr, coffee_files[i].page); //读取文件元数据file_header到hdr

//用法2:static int remove_by_page(coffee_page_t page, int remove_log, int close_fds, int gc_allowed)
coffee_files[i].page = INVALID_PAGE;//将file->page标识为INVALID_PAGE,表示该缓存file项可分配给其他文件用
#define INVALID_PAGE ((coffee_page_t)-1) //注1

max_pages

max_pages含义跟file_header->max_pages相同,即为该文件保留的页面数,加载文件load_file函数将file_headermax_pages赋给filemax_pages

record_count

record_count表示实际的微日志记录数量,不同于file_headerlog_records

references

Contiki提供类多线程编程环境,会有这样的情况,多个线程同时打开一个文件,需要记录引用次数。打开文件cfs_open引用次数++,关闭文件cfs_close引用次数--

flags

flags两种取值:0COFFEE_FILE_MODIFIED,即标识该文件是否含有微日志文件。详情见博文《flags标志位》。

注:

这里用了个小技巧,使得程度更具移植性。因为在cfs-coffee.arch.hcoffee_page_t有可能是8位,也有可能是16位,源码如下:

#if COFFEE_PAGES <= 127
  #define coffee_page_t u8_t
#elif COFFEE_PAGES <= 0x7FFF
  #define coffee_page_t u16_t
#endif

INVALID_PAGE定义为coffee_page_t-1,如果coffee_page_t是8位,那么INVALID_PAGE0xFF,如果coffee_page_t是16位,那么INVALID_PAGE0xFFFF,可以自适应coffee_page_t类型的变化,更具移植性。关于这个技巧可参见博文《具有可移植的无穷大定义》。

2. file_header

结构体file_header源码如下:

struct file_header
{
  coffee_page_t log_page;
  uint16_t log_records;
  uint16_t log_record_size;
  coffee_page_t max_pages;
  uint8_t deprecated_eof_hint;
  uint8_t flags;
  char name[COFFEE_NAME_LENGTH];
};

log_page

不同于file->pagelog_page指向微日志的第一页(如果配置了微日志)。

log_records

表示日志可以容纳的记录数量(log records denotes the number of records that the log can hold)

log_record_size

log_record_size表示微日志文件大小,如果为0,则设置成默认值(见cfs-coffee-arch.h文件配置#define COFFEE_LOG_SIZE 128)。

max_pages

max_pages指为文件保留着页面数(The max pages field specifies the amount of pages that have been reserved for the file)

deprecated_eof_hint

因为文件头不能存储文件长度(缘于文件长度经常变化着),所以用deprecated_eof_hint指向文件的最后一个字节。文件关闭时,如果文件长度增加则需更新deprecated_eof_hint。事实上,纵观源码,deprecated_eof_hint都没用到,而是用file->end存储文件末尾的位置(打开文件时,用蛮力法扫描得到该文件的末尾位置)。

flags

flags反映了文件当前状态(The flag field tells us the current state),用了6个位,分别是ALOMIV,详情请见博文《flags标志位》。

name

文件名,其中文件长度COFFEE_NAME_LENGTH可配置,在contiki/cpu/平台(如arm/stm32f103)/cfs-coffee-arch.h

3. file与file_header联系

3.1 联系

file_header存放物理文件的元数据(即描述该物理文件),而file可以理解成物理文件元数据的内存表示,但又不是完全缓存,因为filefile_header成员变量差别甚大。为了提高性能,Contiki具体是这样做的:所有打开的文件都通过文件描述符fd(非负整数,类似于Linux)引用,将file_desc组织成一个数组file_desc coffee_fd_set[COFFEE_FD_SET_SIZE],每个fd对应于一个file_desc(以数组下标的形式),每个file_desc对应于一个file。通过数组file_desc coffee_fd_set[COFFEE_FD_SET_SIZE]下标(即文件描述符fd)就可以访问file,而file存储物理文件的一些信息,这样也就可以访问物理文件了。

3.2 page与log_page

file_page是指向物理文件的第一页,即存放文件元数据file_header的页。而file_header->log_pages指向微日志的第一页(如果配置了微日志)。

3.3 file与file_header的flags

file_header->flags记录的是整个物理文件的相关信息(即元数据),而file->flags只用来标识文件是否有微日志存在。详情请见博文《flags标志位》。

3.4 deprecated_eof_hint与end

file_header->deprecated_eof_hintfile->end都存储文件的末尾的位置,但事实上,纵观源码,file_header->deprecated_eof_hint是没有用到的(这点与官方论文有出入),也就是说物理上没有存储文件的末尾位置,而是每次打开文件时,通过蛮力扫描,得到文件末尾位置,存入file->end

3.5 record_count与log_records

这两个关系,我也不是搞得很清楚。给我感觉就是,file_header->log_records是指文件创建时的指定的微日志记录数量,默认的情况会是COFFEE_LOG_SIZE/log_record_sizelog_record_size默认情况会是COFFEE_PAGE_SIZE,见adjust_log_config函数)。而file->record_count是实际上的微日志记录数量。

本文系Spark & Shine原创,转载需注明出处本文最近一次修改时间 2022-03-21 15:07

results matching ""

    No results matching ""