文件IO 文件位置偏移量

每一个文件被打开之后,内核都维护一个所谓的当前文件位置偏移量,读和写操作都会对这个偏移量产生影响。



拓展:



文件位置偏移量被存放到内核的file结构体中,应用程序可以通过lseek()/和fseek()来调整。需要额外注意的是:



第一:每执行一次open()/fopen()内核就会记录一个文件位置偏移量,这意味着多次打开同一个文件时,内核会记录多个独立的“文件位置偏移量”,这种特性有利于多线程操作文件。



第二:针对一次文件打开操作,读和写影响的是同一个文件位置偏移量。



第三:管道型文件(比如fifo、socket、pipe)不可以设置文件位置偏移量。



f.seek(offset,whence)


#offset代表文件的指针的偏移量,单位是字节bytes
#whence代表参考物,有三个取值
#0:参照文件的开头
#1:参照当前文件指针所在位置
#2: 参照文件末尾
#ps:快速移动到文件末尾f.seek(0,2)
https://www.cnblogs.com/wangcheng9418/p/9305744.html



可以看出fork后,父子进程的文件偏移量是相同的
进程用struct file结构来记录打开文件的信息,进程每次打开一个文件,就会用一个struct file结构来记录信息,同一个文件打开多次(没有close)也会得到多个struct file结构。struct file->f_path.dentry、struct file->f_inode、struct dentry->d_inode这些字段是vfs的基本组件,构成了vfs的基本框架,不过不属于本文的描述范围,本文关注struct file->f_pos字段,该字段用于记录被打开的文件的偏移量,read、write操作就是从该偏移量处开始操作文件的。



1)进程管理文件的数据结构struct files_struct
文件系统模块涉及到struct file、struct dentry、struct inode



2)父子进程修改struct file结构的字段时,对方能看到吗?
根据常识父子进程是独立的,修改struct file结构的字段值对方是看不到的,但是根据前面分析(父子进程的struct file都是一样的(父子进程都指向同一个struct file),所以文件偏移量struct file->f_pos也一样),父子进程操作的是同一个struct file,一个人修改,另一个人应该能看到啊—–这是错误的。



这里涉及到写时复制机制,父子进程都指向同一个struct file,这只是指父子进程struct file数据结构的虚拟地址是相同的,但是物理地址是不同的。fork进程时,父进程的页表项被标记为只读,当父子进程中任意一个写值时,会产生缺页异常,建立虚拟地址与物理地址的映射关系,然后在新的物理地址上进行写,从而与另一个进程独立,不会相互影响。



3)init进程的struct files_struct
fork进程会将父进程struct files_struct中的信息复制给子进程,那么最原始的struct files_struct是哪里来的
https://blog.csdn.net/geshifei/article/details/86904018

https://blog.csdn.net/weixin_45819795/article/details/103299430



logagent是部署在每台服务器上的一个deamon进程,起着日志数据的传输通道。对外提供http服务拉取日志,结构如下:



其中,



filter:请求过滤器,负责访问源解析统计,权限认证等
container:包含了正在访问的文件句柄集合,当日志滚动文件名变更发生时可以防止错误定位
handler:获取日志数据的处理器,采用偏移量随机读取的方式
storer:保存用户成功获取的文件位点信息



1.长链接 vs 短链接



  http1.1默认支持长链接,避免重复建立连接带来的性能消耗。但长链接会占用系统资源,在大量请求时存在隐患,故选择短链接方式,即关闭http中的keep-alive


2.请求规范



  http://127.0.0.1:8080/get?file=/home/admin/tomcat/logs/catalina.log&user=test&pwd=123456


其中,



         get:指明是获取日志数据的请求

file:日志文件的全路径,支持通配符*指定某目录下所有的日志文件

user:请求用户

pwd:请求用户的授权密钥,md5加密 3.稳定性

logagent是业务部署在一起的,考虑稳定性做如下限制


一台线上实体机同时允许的单用户最大访问文件数100
一台线上实体机同时允许的最大链接数200
一台线上实体机允许单用户单次拉取日志的最大大小为20M
拉取日志的速度赶不上打日志速度时,须提高限制大小或并发度



如果logagent意外down掉,支持恢复后从上次位点继续获取数据



4.性能方案



因为agnt是java编写的,主要考虑满负荷运行下进程gc对宿主业务系统带来的各指标影响,具体以测试为准


5.安全策略



访问文件的权限
请求中验证用户和授权密码
连接agent的收集机器白名单授权
6.日志模块设计



编码:统一采用utf-8
内容截取
普通的日志文件是一条条的纪录,以换行符进行分隔,在进行截取时应获取一条完整的日志,即



 当前位点+ 单次最大支持传递量= 换行符,按正常截取

当前位点 + 单次最大支持传递量!= 换行符,往前找最近一个换行符截取

当前位点 + 单次最大支持传递量> 文件end,直接截取到文件end

扩展考虑支持用户指定分隔符进行切割


位点存取
按用户存储文件的位点信息,一个文件可以支持多个用户同时拉取数据,即该文件会分别保留这些用户的位点信息,保留路径由logagent默认指定,采用拉取成功后异步更新的策略



支持日志滚动
支持当日志文件发生滚动时,可以定位到未拉取完的旧文件。保留文件的句柄(inode),在每次拉取数据时获取当前文件大小,直到该句柄文件内容被拉取完成



7.运维支持



权限:包括机器、文件、白名单
提供获取某应用的所有ip地址等基础服务
装机部署&远程控制
http://blog.sina.com.cn/s/blog_879e61a00102vyeo.html



linux系统中的每个文件都被赋予一个唯一的数值,这个数值称做索引节点。索引节点存储在一个称作索引节点表< inode table>中,该表在磁盘格式化时被分配。每个实际的磁盘或分区都有其自己的索引节点表。一个索引节点包含文件的所有信息,包括磁盘上数据的地址和文件类型。文件类型包括如普通文件、目录和特殊文件这样的信息。
linux硬盘组织方式为:引导区、超级块(superblock),索引结点(inode),数据块(datablock),目录块(diredtory block)。其中超级块中包含了关于该硬盘或分区上的文件系统的整体信息,如文件系统的大小等;超级块后面的数据结构是索引结点,它包含了针对某一个具体文件的几乎全部信息,如文件的存取权限、所有者、大小、建立时间以及对应的目录块和数据块等;数据块是真正存储文件内容的位置。但是索引结点中不包括文件的名字,文件名是放在目录块里的。目录块里包含有文件的名字以及此文件的索引结点编号。



http://blog.chinaunix.net/uid-7471615-id-83766.html



Category linux