当前位置: 首页> 科技> 名企 > 淄博建设网站公司_甘肃省人民政府官网首页_如何在网上推广_seo教程自学入门教材

淄博建设网站公司_甘肃省人民政府官网首页_如何在网上推广_seo教程自学入门教材

时间:2025/7/12 9:52:59来源:https://blog.csdn.net/weixin_42766184/article/details/146890283 浏览次数:0次
淄博建设网站公司_甘肃省人民政府官网首页_如何在网上推广_seo教程自学入门教材

一、背景

在一个比较注重性能的系统上,共享内存的使用肯定非常普遍。为了能更好的了解系统里共享内存的使用,比如创建、删除等操作,我们是可以对其进行监控的。

这篇博客以共享内存的创建监控为例来介绍如何监控共享内存。

这里有一个概念就是/dev/shm下的文件,是放在内存上的文件,这个/dev/shm如下面的df -h命令可以看到,它是一个tmpfs文件系统,而系统上的tmpfs文件系统其实有很多,/dev/shm是其中一个。我们其实在监控共享内存时,一般来说都是只感兴趣/dev/shm下的也就是shm_open这套shmem接口来创建的共享内存文件。

在下面第二章里,我们贴出改动源码和结果展示,在第三章里,我们给出源码分析和相关细节分析。

二、源码和结果展示

2.1 内核shmem.c里的改动部分

在内核shmem.c里增加下面这段代码:


static u32 _enable_output_path = 0;void shmem_set_enable_output_path(void) {_enable_output_path = 1;
}
EXPORT_SYMBOL_GPL(shmem_set_enable_output_path);void shmem_set_disable_output_path(void) {_enable_output_path = 0;
}
EXPORT_SYMBOL_GPL(shmem_set_disable_output_path);#include <linux/blk_types.h>
#include <linux/blkdev.h>#include <linux/fs.h>
#include <linux/mount.h>#if 0
void print_superblock_root_path(struct super_block *sb) {struct dentry *root_dentry = sb->s_root;char path_buffer[256];struct path root_path;root_path.dentry = root_dentry;root_path.mnt = root_dentry->d_sb->s_root->mnt; // 获取挂载点if (d_path(&root_path, path_buffer, sizeof(path_buffer)) < 0) {printk(KERN_ERR "Failed to get path\n");} else {printk(KERN_INFO "Root path: %s\n", path_buffer);}
}
#endifextern struct dentry* get_dentry_by_sb_currns(struct super_block *sb);static struct super_block *_psb_devshm = NULL;int outputfullpath(const char* i_prefix, struct inode *i_inode, struct dentry* i_dentry)
{struct dentry *dentry;char *buffer, *buffer_mount1, *buffer_mount2, *buffer_mount3, *path;buffer = (char *)__get_free_page(GFP_KERNEL);if (!buffer)return -ENOMEM;buffer_mount1 = (char *)__get_free_page(GFP_KERNEL);if (!buffer_mount1)return -ENOMEM;buffer_mount2 = (char *)__get_free_page(GFP_KERNEL);if (!buffer_mount2)return -ENOMEM;buffer_mount3 = (char *)__get_free_page(GFP_KERNEL);if (!buffer_mount3)return -ENOMEM;if (_psb_devshm) {if (i_inode->i_sb != _psb_devshm) {printk("not /dev/shm!\n");goto free_label;}}hlist_for_each_entry(dentry, &i_inode->i_dentry, d_u.d_alias) {path = dentry_path_raw(dentry, buffer, PAGE_SIZE);if (IS_ERR(path)){continue;   }{struct dentry* de = get_dentry_by_sb_currns(i_inode->i_sb);char *path1 = dentry_path_raw(de, buffer_mount1, PAGE_SIZE);char *path2 = NULL;char *path3 = NULL;//printk("path1 = %s\n", path1);if (de->d_sb) {if (strcmp(path1, "/") != 0) {de = get_dentry_by_sb_currns(de->d_sb);path2 = dentry_path_raw(de, buffer_mount2, PAGE_SIZE);//printk("path2 = %s\n", path2);if (de->d_sb) {if (strcmp(path2, "/") != 0) {de = get_dentry_by_sb_currns(de->d_sb);path3 = dentry_path_raw(de, buffer_mount3, PAGE_SIZE);//printk("path3 = %s\n", path3);}else {path2 = NULL;}}}else {path1 = NULL;}}else {goto free_label;}if (path1 && path2) {if ((strcmp(path2, "/dev") == 0) && (strcmp(path1, "/shm") == 0)) {if (strcmp(path3, "/") == 0) {printk("[/dev/shm][%s]dentry name = %s , path = %s, i_dentry=%s, i_dentry->d_parent.name=%s"" sb->s_root.name=%s (d_parent==sb->s_root)[%u]\n", i_prefix, dentry->d_name.name, path, i_dentry->d_name.name, i_dentry->d_parent->d_name.name, i_inode->i_sb->s_root->d_name.name,(i_dentry->d_parent == i_inode->i_sb->s_root)?1:0);_psb_devshm = i_inode->i_sb;goto free_label;}}}// if (path2) {//     printk("dentry name = %s%s%s\n", path2, path1, path);// }// else if (path1) {//     printk("dentry name = %s%s\n", path1, path);// }// else {//     printk("dentry name = %s\n", path);// }}}free_label:free_page((unsigned long)buffer);free_page((unsigned long)buffer_mount1);free_page((unsigned long)buffer_mount2);free_page((unsigned long)buffer_mount3);//spin_unlock(&inode->i_lock);return 0;
}

然后在shmem.c里的shmem_mknod函数里增加下面这段红框部分的代码:

另外,和之前的博客 获取inode的完整路径包含挂载的路径_内核如何通过inode获取完整路径-CSDN博客 里增加在namespace.c里 3.1 一节里讲的内容一样,增加了下面这个函数:

struct dentry* get_dentry_by_sb_currns(struct super_block *sb)
{struct mnt_namespace *mnt_ns = current->nsproxy->mnt_ns;struct mount *mnt;struct dentry* dentry = NULL;lock_mount_hash();list_for_each_entry(mnt, &mnt_ns->list, mnt_list) {if (mnt->mnt.mnt_sb == sb) {dentry = mnt->mnt_mountpoint;break;}}unlock_mount_hash();return dentry;
}
EXPORT_SYMBOL_GPL(get_dentry_by_sb_currns);

2.2 内核模块用来启动/关闭shmem的这个调试判断和打印

#include <linux/module.h>
#include <linux/capability.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <linux/proc_fs.h>
#include <linux/ctype.h>
#include <linux/seq_file.h>
#include <linux/poll.h>
#include <linux/types.h>
#include <linux/ioctl.h>
#include <linux/errno.h>
#include <linux/stddef.h>
#include <linux/lockdep.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/wait.h>
#include <linux/init.h>
#include <asm/atomic.h>
#include <trace/events/workqueue.h>
#include <linux/sched/clock.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/tracepoint.h>
#include <trace/events/osmonitor.h>
#include <trace/events/sched.h>
#include <trace/events/irq.h>
#include <trace/events/kmem.h>
#include <linux/ptrace.h>
#include <linux/uaccess.h>
#include <asm/processor.h>
#include <linux/sched/task_stack.h>
#include <linux/nmi.h>
#include <asm/apic.h>
#include <linux/version.h>
#include <linux/sched/mm.h>
#include <asm/irq_regs.h>
#include <linux/kallsyms.h>
#include <linux/kprobes.h>MODULE_LICENSE("GPL");
MODULE_AUTHOR("zhaoxin");
MODULE_DESCRIPTION("Module for kernel get time.");
MODULE_VERSION("1.0");extern void shmem_set_enable_output_path(void);
extern void shmem_set_disable_output_path(void);static int __init testtmpfs_init(void)
{shmem_set_enable_output_path();return 0;
}static void __exit testtmpfs_exit(void)
{shmem_set_disable_output_path();
}module_init(testtmpfs_init);
module_exit(testtmpfs_exit);

2.3 结果展示

我们先在/dev/shm里创建文件夹和创建新的文件都可以打印出加的调试打印:

如果我们自己mount一个tmpfs的分区,然后在里面创建文件并不会打印出/dev/shm目录下才会打印的上图里的打印,而是打印下图里的not /dev/shm字样:

三、源码分析和相关细节分析

3.1 tmpfs文件系统和shmem接口的应用

shmem.c文件是服务于系统里的所有tmpfs文件系统里的操作。而tmpfs系统在系统里的情况非常普遍:

而我们感兴趣的往往是/dev/shm这样的使用shm的接口的程序应用,有关的例子如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>           // For O_* constants
#include <sys/mman.h>       // For shm_open, mmap
#include <unistd.h>         // For close
#include <sys/stat.h>       // For mode constants
#include <sys/types.h>
#include <errno.h>int main() {const char *name = "/my_shm"; // 共享内存的名称const size_t size = 1024*1024*1024;      // 共享内存的大小int shm_fd;                    // 共享内存文件描述符void *ptr;                     // 指向共享内存的指针// 创建共享内存对象shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);if (shm_fd == -1) {perror("shm_open");exit(EXIT_FAILURE);}// 调整共享内存的大小if (ftruncate(shm_fd, size) == -1) {perror("ftruncate");exit(EXIT_FAILURE);}// 将共享内存映射到进程的地址空间ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);if (ptr == MAP_FAILED) {perror("mmap");exit(EXIT_FAILURE);}getchar();// 锁定共享内存区域中的页if (mlock(ptr, size) != 0) {perror("mlock");exit(EXIT_FAILURE);}getchar();// 写入数据到共享内存sprintf((char*)ptr, "Hello, Shared Memory!");// 读取数据printf("Data from shared memory: %s\n", (char *)ptr);// 解锁共享内存区域if (munlock(ptr, size) != 0) {perror("munlock");exit(EXIT_FAILURE);}// 解除映射if (munmap(ptr, size) == -1) {perror("munmap");exit(EXIT_FAILURE);}// 关闭共享内存对象if (close(shm_fd) == -1) {perror("close");exit(EXIT_FAILURE);}// 删除共享内存对象if (shm_unlink(name) == -1) {perror("shm_unlink");exit(EXIT_FAILURE);}return 0;
}

3.2 shmem.c里的shmem_mknod函数

tmpfs系统下的创建文件夹和创建文件的操作都会走到shmem_mknod函数里来,如下图依次是创建文件夹和创建文件的函数shmem_mkdir和shmem_create,这两个函数最终都是调用的shmem_mknod函数:

所以,我们在shmem_mknod函数里加监测逻辑是能覆盖tmpfs文件系统里的创建文件夹和创建文件的行为。

3.3 shmem.c里的shmem_link和shmem_symlink

shmem.c里还有一些其他接口,如下图里的shmem_link是指硬链接,shmem_symlink是指软链接:

有关硬链接和软链接及相关的inode,dentry的实验见之前的博客 关于inode,dentry结合软链接及硬链接的实验-CSDN博客。

3.4 shmem_mknod函数里增加的“判断是不是/dev/shm下的mknod事件”的逻辑

我们在shmem_mknod里增加了判断逻辑,检查是否是/dev/shm下的mknod事件,用的依次判断是否是/dev和/shm这两级super_block的mnt_mountpoint,而获取mnt_mountpoint的这块核心逻辑在之前的博客 获取inode的完整路径包含挂载的路径_内核如何通过inode获取完整路径-CSDN博客 里进行了分析:

在shmem.c里使用了该get_dentry_by_sb_currns函数进行了几级mountpoint的dentry的记录,然后判断完整的mountpoint的dentry链是否是/dev/shm:

如果判断到是/dev/shm这个完整路径,就记录下来这个super_block指针:

这样,接下来的判断就会更加快了:

关键字:淄博建设网站公司_甘肃省人民政府官网首页_如何在网上推广_seo教程自学入门教材

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: