本篇内容介绍了“linux1.2.13 file结构体管理是怎样的”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
操作系统为进程维护了打开的文件列表,每个进程维护了一个file数组字段(struct file * fd[NR_OPEN]);每个元素指向一个file结构体。每个file结构体有一个字段指向inode结构体,inode管理这个文件的内容、权限等信息。这里分析的是file结构体的管理。
下面是file结构体的定义
struct file { mode_t f_mode; loff_t f_pos; unsigned short f_flags; unsigned short f_count; off_t f_reada; struct file *f_next, *f_prev; int f_owner; /* pid or -pgrp where SIGIO should be sent */ struct inode * f_inode; struct file_operations * f_op; unsigned long f_version; void *private_data; /* needed for tty driver, and maybe others */};
下面是对file结构体的管理,当进程打开一个文件的时候,就可能需要从中申请一个file结构体。
/* * linux/fs/file_table.c * * Copyright (C) 1991, 1992 Linus Torvalds */#include <linux/fs.h>#include <linux/string.h>#include <linux/mm.h>struct file * first_file;int nr_files = 0;// 双向循环链表,first_file指向头指针,头插法插入一个节点static void insert_file_free(struct file *file){ file->f_next = first_file; file->f_prev = first_file->f_prev; file->f_next->f_prev = file; file->f_prev->f_next = file; first_file = file;}// 删除一个节点static void remove_file_free(struct file *file){ // 如果要删除的节点是第一个节点,则更新头指针,指向下一个节点 if (first_file == file) first_file = first_file->f_next; // 如果被删除的节点后面还有节点,则需要更新下一个节点的prev指针,指向当前节点的上一个节点 if (file->f_next) file->f_next->f_prev = file->f_prev; // 同理,更新上一个节点的next指针,指向被删除节点的下一个节点 if (file->f_prev) file->f_prev->f_next = file->f_next; // 置空 file->f_next = file->f_prev = NULL;}// file插入链表,成为最后一个节点static void put_last_free(struct file *file){ // 保证file脱离了原来的链表 remove_file_free(file); // 插入链表,但是不更新头指针first_file,所以file成为最后一个节点 file->f_prev = first_file->f_prev; file->f_prev->f_next = file; file->f_next = first_file; file->f_next->f_prev = file;}void grow_files(void){ struct file * file; int i; // 申请一页内存 file = (struct file *) get_free_page(GFP_KERNEL); if (!file) return; // i=PAGE_SIZE/sizeof(struct file),即一页可以存多少个节点,更新最大节点数 nr_files+=i= PAGE_SIZE/sizeof(struct file); /* 当前是初始化的时候,先初始化一个节点,需要初始化的节点数减一,执行insert_file_free 前需要保证first_file非空,见insert_file_free中的first_file */ if (!first_file) file->f_next = file->f_prev = first_file = file++, i--; // 形成一个链表 for (; i ; i--) insert_file_free(file++);}// file链表初始化unsigned long file_table_init(unsigned long start, unsigned long end){ first_file = NULL; return start;}// 获取一个可以的file结构体struct file * get_empty_filp(void){ int i; struct file * f; if (!first_file) grow_files();repeat: // nr_files是链表的总节点数 for (f = first_file, i=0; i < nr_files; i++, f = f->f_next) // 找到空闲的节点 if (!f->f_count) { // 脱离链表 remove_file_free(f); // 清空内存 memset(f,0,sizeof(*f)); // 插入链表末尾 put_last_free(f); // 标记已使用 f->f_count = 1; f->f_version = ++event; return f; } // 没有找到空闲节点,扩容,再找 if (nr_files < NR_FILE) { grow_files(); goto repeat; } return NULL;}
从图中我们可以看出,系统维护了一个双向循环的链表,保存了一系列已使用和未使用的file结构体。first_file指针执行第一个空闲的节点,进程申请file结构体的时候就把该节点放到链表结尾。first_file指针指向下一个空闲节点。如果没有空闲节点了,就会自动扩容。
“linux1.2.13 file结构体管理是怎样的”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/u/4217331/blog/4379677