第10章 无持久存储的文件系统 (3)

目录

[10.2 简单文件系统](#10.2 简单文件系统)

[10.2.1 顺序文件](#10.2.1 顺序文件)

[10.2.2 用libfs编写文件系统](#10.2.2 用libfs编写文件系统)

[10.2.3 调试文件系统](#10.2.3 调试文件系统)

[10.2.4 伪文件系统](#10.2.4 伪文件系统)

[10.3 sysfs](#10.3 sysfs)

[10.3.1 概述](#10.3.1 概述)

[10.3.2 数据结构](#10.3.2 数据结构)

[10.3.3 装载文件系统](#10.3.3 装载文件系统)

[10.3.4 文件和目录操作](#10.3.4 文件和目录操作)

[10.3.5 向sysfs添加内容](#10.3.5 向sysfs添加内容)

[10.4 小结](#10.4 小结)


本专栏文章将有70篇左右,欢迎+关注,查看后续文章。

10.2 简单文件系统

如:libfs,seq_file,debugfs。

10.2.1 顺序文件

读写 proc 文件时,默认只使用一页内存。若proc文件太大,则用 seq_file。

seq_file优点:

不需要开发者直接管理保存数据的内存缓冲区。

简化了向用户空间输出内核数据。

1. 编写顺序文件处理函数

proc_create("netlink", 0, net->proc_net, &netlink_seq_fops);

struct file_operations netlink_seq_fops = {

.open = netlink_seq_open,

.read = seq_read,

//将调用struct seq_operations 中 start,next,stop,show等函数指针。

.llseek = seq_lseek,

};

struct seq_operations netlink_seq_ops = {

.start = netlink_seq_start, //开始读数据项。

.stop = netlink_seq_stop, //停止数据项。

.next = netlink_seq_next, //遍历下一个要处理的数据项。

.show = netlink_seq_show, //打印数据项到临时缓冲区。

};

若 file_operations 中 .llseek = no_llseek() ;

表示设备无法seek。

Kprobe介绍:

作用:

  1. 内核调试。

  2. 收集内核和应用程序的性能信息,如函数执行时间、调用次数等。

原理:

在指定函数中插入探测点,可在探测点前或探测点后执行对应回调函数。

注意:

需要硬件架构支持。

struct kprobe {

kprobe_opcode_t *addr; // 探测点位置。

kprobe_pre_handler_t pre_handler; // 探测指令被执行前的回调。

kprobe_post_handler_t post_handler; // 探测指令执行完毕后的回调。

kprobe_fault_handler_t fault_handler; // 当内存访问出错时被调用。

}

struct file_operations debugfs_kprobes_operations = {

.open = kprobes_open,

.read = seq_read,

.llseek = seq_lseek,

.release = seq_release,

};

struct seq_operations kprobes_seq_ops = {

.start = kprobe_seq_start,

.next = kprobe_seq_next, // 偏移+1=索引+1。

.stop = kprobe_seq_stop, // 什么也不做。

.show = show_kprobe_addr, // 生成文件内容。

};

int kprobes_open(struct inode *inode, struct file *filp)

{

return seq_open(filp, &kprobes_seq_ops);

}

Kprobe将事件发生时将相关数据记录到文件中。

举例:

使用Kprobe跟踪网络流量。

  1. 跟踪TCP连接事件:

使用Kprobe在内核TCP连接函数中插入断点,当TCP连接建立或关闭时,将信息记录到顺序文件中。

记录的信息包括:源地址、目标地址、连接建立 / 关闭时间戳等。

  1. 跟踪收发包:

在收发包函数中插入断点,当有数据传输时,记录相关信息到顺序文件中。

记录的信息包括:源地址、目标地址、数据包大小、协议类型等信息。

Jprobe:Kprobe一个扩展。

编程举例:

struct jprobe tcp_conn_open_probe = {

.entry = (kprobe_opcode_t *) tcp_conn_open, //自定义的断点处理函数。

.kp = {

.symbol_name = "tcp_v4_connect", //需要跟踪的内核函数。

},

};

struct jprobe tcp_conn_close_probe = {

.entry = (kprobe_opcode_t *) tcp_conn_close,

.kp = {

.symbol_name = "inet_csk_destroy_sock",

},

};

int tcp_conn_init(void)

{

register_jprobe( &tcp_conn_open_probe );

register_jprobe( &tcp_conn_close_probe );

}

void tcp_conn_exit(void)

{

// 取消注册Kprobe

unregister_jprobe(&tcp_conn_open_probe);

unregister_jprobe(&tcp_conn_close_probe);

}

10.2.2 用libfs编写文件系统

libfs:一个库,用于创建特定用途的小型文件系统,适合无后备存储器。

编程举例:

struct file_operations simple_dir_operations = {

.open = dcache_dir_open,

.release = dcache_dir_close,

.llseek = dcache_dir_lseek,

.read = generic_read_dir,

.readdir = dcache_readdir,

.fsync = noop_fsync,

};

struct inode_operations simple_dir_inode_operations = {

.lookup = simple_lookup;

};

10.2.3 调试文件系统

DebugFS:

原理:

基于libfs实现。

使用场景:

快速查看或修改模块/内核的变量,无需重新编译内核或模块。

对应目录:

/sys/kernel/debug

编译选项:

CONFIG_DEBUG_FS

编程接口:

debugfs_kprobe_init

debugfs_create_file

debugfs_create_dir

debugfs_create_symlink

10.2.4 伪文件系统

如:bdev文件系统。

bdev作用:

集群块设备所有的inode,只有内核可见。

struct file_system_type bd_type = {

.name = "bdev",

.mount = bd_mount,

.kill_sb = kill_anon_super,

}

struct dentry *bd_mount(struct file_system_type *fs_type, int flags, char *dev_name, void *data)

{

return mount_pseudo(fs_type, "bdev:", &bdev_sops, NULL, BDEVFS_MAGIC);

}

10.3 sysfs

作用:

向用户层导出内核对象。

显示kobject拓扑。

提供装载点/sys。

10.3.1 概述

kobject被层次化组织。

如果一个kobject没有父对象,将其放置到所在kset所属的kobject对应目录中。

每个kobject表示sysfs中一个目录。而attribute表示sysfs中一个文件。

kobject_add函数

作用:导出kobject到sys文件系统。

10.3.2 数据结构

属性:

struct attribute { //代表sysfs中一个文件

const char *name;

umode_t mode; //文件访问权限。

};

10.3.3 装载文件系统

struct file_system_type sysfs_fs_type = {

.name = "sysfs",

.mount = sysfs_mount,

.kill_sb = sysfs_kill_sb,

};

sysfs_mount -> sysfs_fill_super

创建根目录的inode

int sysfs_fill_super(struct super_block *sb, void *data, int silent)

{

inode = sysfs_get_inode(sb, &sysfs_root);

//inode->i_fop = &sysfs_file_operations;

}

sysfs_file_operations:后续介绍

10.3.4 文件和目录操作

struct file_operations sysfs_file_operations = {

.read = sysfs_read_file,

//调用ops->show(kobj, attr_sd->s_attr.attr, buffer->page);

.write = sysfs_write_file,

.open = sysfs_open_file,

}

struct kobj_type brport_ktype = {

.sysfs_ops = &brport_sysfs_ops,

};

ops->show();为不同文件自定义,如/sys/bridge

struct sysfs_ops brport_sysfs_ops = {

.show = brport_show, //调用brport_attr->show(p, buf);

.store = brport_store,

};

而 brport_attr->show(p, buf); 是/sys/bridge下不同文件各自定义的,如:

BRPORT_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router, store_multicast_router)

10.3.5 向sysfs添加内容

struct kobj_attribute {

struct attribute attr; //包括文件名,文件权限。

ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr, char *buf);

ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count);

};

10.4 小结

相关推荐
傻啦嘿哟6 分钟前
代理IP在后端开发中的应用与后端工程师的角色
网络·网络协议·tcp/ip
sun0077009 分钟前
ubuntu dpkg 删除安装包
运维·服务器·ubuntu
Red Red11 分钟前
网安基础知识|IDS入侵检测系统|IPS入侵防御系统|堡垒机|VPN|EDR|CC防御|云安全-VDC/VPC|安全服务
网络·笔记·学习·安全·web安全
海岛日记11 分钟前
centos一键卸载docker脚本
linux·docker·centos
oi7740 分钟前
使用itextpdf进行pdf模版填充中文文本时部分字不显示问题
java·服务器
AttackingLin1 小时前
2024强网杯--babyheap house of apple2解法
linux·开发语言·python
吃肉不能购2 小时前
Label-studio-ml-backend 和YOLOV8 YOLO11自动化标注,目标检测,实例分割,图像分类,关键点估计,视频跟踪
运维·yolo·自动化
亚远景aspice2 小时前
ISO 21434标准:汽车网络安全管理的利与弊
网络·web安全·汽车