更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
vfs_file_mapping.c 文件参考

浏览源代码.

结构体

struct  page_mapping
 
struct  file_map
 
struct  file
 

函数

uint init_file_mapping ()
 
static void clear_file_mapping (const struct page_mapping *mapping)
 清除文件映射 更多...
 
static struct page_mappingfind_mapping_nolock (const char *fullpath)
 以无锁的方式通过文件名查找文件映射并返回 更多...
 
void add_mapping (struct file *filep, const char *fullpath)
 增加一个文件映射,这个函数被do_open()函数调用,每打开一次文件就会调用一次 注意不同的进程打开同一个文件,拿到的file是不一样的。 https://blog.csdn.net/cywosp/article/details/38965239 更多...
 
int remove_mapping_nolock (struct page_mapping *mapping)
 删除一个文件映射,需要有个三个地方删除才算断开了文件和内存的联系. 以无锁的方式删除映射 更多...
 
void dec_mapping_nolock (struct page_mapping *mapping)
 无锁方式引用递减,删除或关闭文件时 由 files_close_internal调用 更多...
 
int remove_mapping (const char *fullpath)
 已有锁的方式删除文件映射 更多...
 
void rename_mapping (const char *src_path, const char *dst_path)
 重命名映射 更多...
 
int update_file_path (const char *old_path, const char *new_path)
 更新文件路径 更多...
 
struct file_mapGetFileMappingList (void)
 

变量

定义见于 third_party NuttX include nuttx fs fs h typedef volatile INT32 Atomic
 
static struct file_map g_file_mapping = {0}
 用于挂载所有文件的file_map 更多...
 

函数说明

◆ add_mapping()

void add_mapping ( struct file filep,
const char *  fullpath 
)

增加一个文件映射,这个函数被do_open()函数调用,每打开一次文件就会调用一次 注意不同的进程打开同一个文件,拿到的file是不一样的。 https://blog.csdn.net/cywosp/article/details/38965239

参数
filep
fullpath

在文件 vfs_file_mapping.c147 行定义.

148{
149 int path_len;
150 status_t retval;
151 struct file_map *fmap = NULL;
152 struct page_mapping *mapping = NULL;
153
154 if (filep == NULL || fullpath == NULL) {
155 return;
156 }
157
158 (VOID)LOS_MuxLock(&g_file_mapping.lock, LOS_WAIT_FOREVER);//操作临界区,先拿锁
159 mapping = find_mapping_nolock(fullpath);//是否已有文件映射
160 if (mapping) {
161 LOS_AtomicInc(&mapping->ref);//引用自增
162 filep->f_mapping = mapping;//记录page_mapping的老板
163 mapping->host = filep;//释放锁
164 goto out;
165 }
166
167 path_len = strlen(fullpath);
168
169 fmap = (struct file_map *)zalloc(sizeof(struct file_map) + path_len + 1);
170 if (!fmap) {
171 PRINT_WARN("%s %d, Mem alloc failed.\n", __FUNCTION__, __LINE__);
172 goto out;
173 }
174
175 LOS_AtomicSet(&fmap->mapping.ref, 1);
176
177 fmap->name_len = path_len;
178 (void)strcpy_s(fmap->owner, path_len + 1, fullpath);
179
180 LOS_ListInit(&fmap->mapping.page_list);//初始化文件映射的页表链表,上面将会挂这个文件映射的所有虚拟内存页
181 LOS_SpinInit(&fmap->mapping.list_lock);//初始化文件映射的自旋锁
182 retval = LOS_MuxInit(&fmap->mapping.mux_lock, NULL);//初始化文件映射的互斥锁
183 if (retval != LOS_OK) {
184 PRINT_ERR("%s %d, Create mutex for mapping.mux_lock failed, status: %d\n", __FUNCTION__, __LINE__, retval);
185 goto out;
186 }
187
188 LOS_ListTailInsert(&g_file_mapping.head, &fmap->head);//将文件映射结点挂入全局链表
189
190 filep->f_mapping = &fmap->mapping;//<file,file_map>之间互绑
191 filep->f_mapping->host = filep;//<file,file_map>之间互绑,从此相亲相爱一家人
192
193out:
195}
STATIC INLINE VOID LOS_AtomicInc(Atomic *v)
Atomic addSelf.
Definition: los_atomic.h:253
STATIC INLINE VOID LOS_AtomicSet(Atomic *v, INT32 setVal)
Atomic setting.
Definition: los_atomic.h:147
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
Definition: los_list.h:104
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListTailInsert(LOS_DL_LIST *list, LOS_DL_LIST *node)
Insert a node to the tail of a doubly linked list.
Definition: los_list.h:244
LITE_OS_SEC_TEXT UINT32 LOS_MuxInit(LosMux *mutex, const LosMuxAttr *attr)
初始化互斥锁
Definition: los_mux.c:262
LITE_OS_SEC_TEXT UINT32 LOS_MuxUnlock(LosMux *mutex)
释放锁
Definition: los_mux.c:559
LITE_OS_SEC_TEXT UINT32 LOS_MuxLock(LosMux *mutex, UINT32 timeout)
拿互斥锁,
Definition: los_mux.c:437
VOID LOS_SpinInit(SPIN_LOCK_S *lock)
Definition: los_spinlock.c:37
int status_t
Definition: los_typedef.h:205
void * zalloc(size_t size)
Definition: malloc.c:91
struct page_mapping mapping
每个文件都有唯一的page_mapping标识其在内存的身份
char * owner
LOS_DL_LIST head
链表节点,用于挂到g_file_mapping上
struct page_mapping * f_mapping
SPIN_LOCK_S list_lock
LOS_DL_LIST page_list
struct file * host
ARG_NUM_3 ARG_NUM_1 ARG_NUM_2 ARG_NUM_2 ARG_NUM_3 ARG_NUM_1 ARG_NUM_4 ARG_NUM_2 ARG_NUM_2 ARG_NUM_5 ARG_NUM_2 void
static struct page_mapping * find_mapping_nolock(const char *fullpath)
以无锁的方式通过文件名查找文件映射并返回
static struct file_map g_file_mapping
用于挂载所有文件的file_map
函数调用图:

◆ clear_file_mapping()

static void clear_file_mapping ( const struct page_mapping mapping)
static

清除文件映射

在文件 vfs_file_mapping.c109 行定义.

110{
111 unsigned int i = 3; /* file start fd */
112 struct file *filp = NULL;
113
114 while (i < CONFIG_NFILE_DESCRIPTORS) {
115 filp = &tg_filelist.fl_files[i];
116 if (filp->f_mapping == mapping) {
117 filp->f_mapping = NULL;
118 }
119 i++;
120 }
121}
这是这个函数的调用关系图:

◆ dec_mapping_nolock()

void dec_mapping_nolock ( struct page_mapping mapping)

无锁方式引用递减,删除或关闭文件时 由 files_close_internal调用

在文件 vfs_file_mapping.c227 行定义.

228{
229 if (mapping == NULL) {
230 return;
231 }
232
233 (VOID)LOS_MuxLock(&g_file_mapping.lock, LOS_WAIT_FOREVER);
234 if (LOS_AtomicRead(&mapping->ref) > 0) {
235 LOS_AtomicDec(&mapping->ref);
236 }
237
238 if (LOS_AtomicRead(&mapping->ref) <= 0) {
239 remove_mapping_nolock(mapping);
240 } else {
241 OsFileCacheFlush(mapping);
242 }
243
245}
STATIC INLINE INT32 LOS_AtomicRead(const Atomic *v)
Atomic read. | 读取32bit原子数据
Definition: los_atomic.h:123
STATIC INLINE VOID LOS_AtomicDec(Atomic *v)
Atomic auto-decrement. | 对32bit原子数据做减1
Definition: los_atomic.h:323
VOID OsFileCacheFlush(struct page_mapping *mapping)
文件缓存冲洗,把所有fpage冲洗一边,把脏页洗到dirtyList中,配合OsFileCacheRemove理解
int remove_mapping_nolock(struct page_mapping *mapping)
删除一个文件映射,需要有个三个地方删除才算断开了文件和内存的联系. 以无锁的方式删除映射
函数调用图:

◆ find_mapping_nolock()

static struct page_mapping * find_mapping_nolock ( const char *  fullpath)
static

以无锁的方式通过文件名查找文件映射并返回

在文件 vfs_file_mapping.c123 行定义.

124{
125 char *map_name = NULL;
126 struct file_map *fmap = NULL;
127 int name_len = strlen(fullpath);
128
129 LOS_DL_LIST_FOR_EACH_ENTRY(fmap, &g_file_mapping.head, struct file_map, head) {
130 map_name = fmap->rename ? fmap->rename: fmap->owner;
131 if ((name_len == fmap->name_len) && !strcmp(map_name, fullpath)) {
132 return &fmap->mapping;
133 }
134 }
135
136 return NULL;
137}
这是这个函数的调用关系图:

◆ GetFileMappingList()

struct file_map * GetFileMappingList ( void  )

在文件 vfs_file_mapping.c364 行定义.

365{
366 return &g_file_mapping;
367}

◆ init_file_mapping()

uint init_file_mapping ( )
 初始化文件映射模块,
 file_map: 每个需映射到内存的文件必须创建一个 file_map,都挂到全局g_file_mapping链表上
 page_mapping: 记录的是<文件,文件页>的关系,一个文件在操作过程中被映射成了多少个页,
 file:是文件系统管理层面的概念
返回
uint

在文件 vfs_file_mapping.c95 行定义.

96{
97 uint ret;
98
99 LOS_ListInit(&g_file_mapping.head);//初始化全局文件映射节点,所有文件的映射都将g_file_mapping.head挂在链表上
100
101 ret = LOS_MuxInit(&g_file_mapping.lock, NULL);//初始化文件映射互斥锁
102 if (ret != LOS_OK) {
103 PRINT_ERR("Create mutex for file map of page cache failed, (ret=%u)\n", ret);
104 }
105
106 return ret;
107}
函数调用图:

◆ remove_mapping()

int remove_mapping ( const char *  fullpath)

已有锁的方式删除文件映射

在文件 vfs_file_mapping.c247 行定义.

248{
249 int ret;
250 struct filelist *f_list = NULL;
251 struct page_mapping *mapping = NULL;
252
253 f_list = &tg_filelist;
254 ret = sem_wait(&f_list->fl_sem);
255 if (ret < 0) {
256 PRINTK("sem_wait error, ret=%d\n", ret);
257 return VFS_ERROR;
258 }
259
260 (VOID)LOS_MuxLock(&g_file_mapping.lock, LOS_WAIT_FOREVER);
261
262 mapping = find_mapping_nolock(fullpath);
263 if (mapping) {
264 ret = remove_mapping_nolock(mapping);
265 }
266
268
269 (void)sem_post(&f_list->fl_sem);
270 return OK;
271}
int sem_post(sem_t *sem)
增加信号量计数
Definition: semaphore.c:139
int sem_wait(sem_t *sem)
获取信号量
Definition: semaphore.c:77
函数调用图:

◆ remove_mapping_nolock()

int remove_mapping_nolock ( struct page_mapping mapping)

删除一个文件映射,需要有个三个地方删除才算断开了文件和内存的联系. 以无锁的方式删除映射

参数
mapping
返回
int

在文件 vfs_file_mapping.c205 行定义.

206{
207 struct file_map *fmap = NULL;
208
209 if (mapping == NULL) {
210 set_errno(EINVAL);
211 return EINVAL;
212 }
213
217 fmap = LOS_DL_LIST_ENTRY(mapping, struct file_map, mapping);
218 LOS_ListDelete(&fmap->head);
219 if (fmap->rename) {
220 LOS_MemFree(m_aucSysMem0, fmap->rename);
221 }
223
224 return OK;
225}
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelete(LOS_DL_LIST *node)
Definition: los_list.h:292
UINT32 LOS_MemFree(VOID *pool, VOID *ptr)
释放从指定动态内存中申请的内存
Definition: los_memory.c:1369
UINT8 * m_aucSysMem0
异常交互动态内存池地址的起始地址,当不支持异常交互特性时,m_aucSysMem0等于m_aucSysMem1。
Definition: los_memory.c:107
LITE_OS_SEC_TEXT UINT32 LOS_MuxDestroy(LosMux *mutex)
销毁互斥锁
Definition: los_mux.c:289
VOID OsFileCacheRemove(struct page_mapping *mapping)
static void clear_file_mapping(const struct page_mapping *mapping)
清除文件映射
函数调用图:
这是这个函数的调用关系图:

◆ rename_mapping()

void rename_mapping ( const char *  src_path,
const char *  dst_path 
)

重命名映射

在文件 vfs_file_mapping.c273 行定义.

274{
275 int ret;
276 char *tmp = NULL;
277 int path_len;
278 struct file_map *fmap = NULL;
279 struct page_mapping *mapping = NULL;
280
281 if (src_path == NULL || dst_path == NULL) {
282 return;
283 }
284
285 path_len = strlen(dst_path);
286
287 /* protect the whole list in case of this node been deleted just after we found it */
288
289 (VOID)LOS_MuxLock(&g_file_mapping.lock, LOS_WAIT_FOREVER);
290
291 mapping = find_mapping_nolock(src_path);
292 if (!mapping) {
293 goto out;
294 }
295
296 fmap = LOS_DL_LIST_ENTRY(mapping, struct file_map, mapping);
297
298 tmp = LOS_MemAlloc(m_aucSysMem0, path_len + 1);
299 if (!tmp) {
300 PRINT_ERR("%s-%d: Mem alloc failed, path length(%d)\n", __FUNCTION__, __LINE__, path_len);
301 goto out;
302 }
303 ret = strncpy_s(tmp, path_len, dst_path, strlen(dst_path));
304 if (ret != 0) {
305 (VOID)LOS_MemFree(m_aucSysMem0, tmp);
306 goto out;
307 }
308
309 tmp[path_len] = '\0';
310 fmap->rename = tmp;
311
312out:
314}
VOID * LOS_MemAlloc(VOID *pool, UINT32 size)
从指定内存池中申请size长度的内存,注意这可不是从内核堆空间中申请内存
Definition: los_memory.c:1123
函数调用图:

◆ update_file_path()

int update_file_path ( const char *  old_path,
const char *  new_path 
)

更新文件路径

在文件 vfs_file_mapping.c316 行定义.

317{
318 struct filelist *f_list = NULL;
319 struct file *filp = NULL;
320 int ret;
321
322 f_list = &tg_filelist;
323 ret = sem_wait(&f_list->fl_sem);
324 if (ret < 0) {
325 PRINTK("sem_wait error, ret=%d\n", ret);
326 return VFS_ERROR;
327 }
328
329 (VOID)LOS_MuxLock(&g_file_mapping.lock, LOS_WAIT_FOREVER);
330 for (int i = 3; i < CONFIG_NFILE_DESCRIPTORS; i++) {
331 if (!get_bit(i)) {
332 continue;
333 }
334 filp = &tg_filelist.fl_files[i];
335 if (filp->f_path == NULL || strcmp(filp->f_path, old_path)) {
336 continue;
337 }
338 int len = strlen(new_path) + 1;
339 char *tmp_path = LOS_MemAlloc(m_aucSysMem0, len);
340 if (tmp_path == NULL) {
341 PRINT_ERR("%s-%d: Mem alloc failed, path length(%d)\n", __FUNCTION__, __LINE__, len);
342 ret = VFS_ERROR;
343 goto out;
344 }
345 ret = strncpy_s(tmp_path, strlen(new_path) + 1, new_path, len);
346 if (ret != 0) {
347 (VOID)LOS_MemFree(m_aucSysMem0, tmp_path);
348 PRINT_ERR("%s-%d: strcpy failed.\n", __FUNCTION__, __LINE__);
349 ret = VFS_ERROR;
350 goto out;
351 }
352 free(filp->f_path);
353 filp->f_path = tmp_path;
354 }
355 ret = LOS_OK;
356
357out:
359 (void)sem_post(&f_list->fl_sem);
360 return ret;
361}
void free(void *ptr)
释放ptr所指向的内存空间
Definition: malloc.c:66
char * f_path
函数调用图:

变量说明

◆ Atomic

定义见于 third_party NuttX include nuttx fs fs h typedef volatile INT32 Atomic

在文件 vfs_file_mapping.c47 行定义.

◆ g_file_mapping

struct file_map g_file_mapping = {0}
static

用于挂载所有文件的file_map

在文件 vfs_file_mapping.c43 行定义.