ext4 mballoc之buddy算法

2023-11-19

buddy bitmap 

根据《Ext4文件系统介绍 - 理论篇_nginux的博客-CSDN博客》我们知道磁盘上有1block 大小(默认4K)data block bitmap,每bit位代表一个block的使用情况,1代表占用,0代表空闲。data block bitmap 可以表示4 * 1024 * 8 = 32768个block,32768 * 4K = 128M正好是1个block group大小。为了加速data block bitmap访问内存中同样会有一份缓存

磁盘block管理为了尽量避免碎片化问题,跟内存管理模块一样同样采用了buddy算法,同时内存构建一个buddy的bitmap,即bitmap buddy。

cat /proc/fs/ext4/xxx/mb_groups 

代码在:fs/ext4/mballoc. :
static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)

#group: free  frags first [ 2^0   2^1   2^2   2^3   2^4   2^5   2^6   2^7   2^8   2^9   2^10  2^11  2^12  2^13  ]
#0    : 18017 2     4262  [ 1     2     1     1     1     2     0     0     0     1     1     0     0     2     ]
#1    : 26581 5     2125  [ 3     3     1     1     2     1     0     1     1     1     1     0     0     3     ]
#2    : 32713 2     27    [ 3     1     3     1     1     1     0     1     1     1     1     1     1     3     ]
#3    : 32639 1     129   [ 1     1     1     1     1     1     1     0     1     1     1     1     1     3     ]
#4    : 24576 1     8192  [ 0     0     0     0     0     0     0     0     0     0     0     0     0     3     ]
#5    : 32634 3     130   [ 2     4     2     3     1     2     2     1     2     0     1     1     1     3     ]
#6    : 32749 1     19    [ 1     0     1     1     0     1     1     1     1     1     1     1     1     3     ]
#7    : 32639 1     129   [ 1     1     1     1     1     1     1     0     1     1     1     1     1     3     ]

free:代表group所有空闲block总数,该值来自于ext4_group_info.bb_free

frags :代表group连续的空闲空间段数目,该值来自于ext4_group_info.bb_fragments

first : 第一个空闲的physical block number该值来自于ext4_group_info.bb_first_free

ext4_mb_seq_groups_show:

 结合代码和上面分析我们知道打印数值来自于ext4_group_info,即通过ext4_get_group_info来获取的:

 最终ext4_group_info来自于EXT4_SB(sb) ext4_sb_info中的成员s_group_info[group],所以s_group_info成员初始化来自哪里?ext4_mb_init_cache,而是ext4_mb_load_buddy就会调用ext4_mb_init_cache,这里init cache就是指保存磁盘data block bitmap的pagecache和buddy bitmap。

ext4_mb_load_buddy->ext4_mb_init_cache->ext4_mb_generate_buddy。

根据ext4_mb_init_cache的代码注释我们知道磁盘data block bitmap和只是内存中构建的(磁盘上无对应数据,unmount时会删除)的buddy bitmap,他们各占用1个block。

 buddy bitmap格式

 

注意:

  1. 上面每个竖线代表二分
  2. 二分表示,每个区间都可以完整表示一个128M block group所有的block的使用情况,1表示占用,0表示空闲。
  3. 内核通过sbi->s_mb_offsets[]和sbi->s_mb_maxs[]两个数据记录每个区域的offset和最大的bit数量。

fs/ext4/mballoc.c : ext4_mb_init构建相应数组:

sbi->s_mb_offset[0] = 0,sbi->s_mb_maxs[1] = 32768
sbi->s_mb_offset[1] = 0,sbi->s_mb_maxs[1] = 16384
sbi->s_mb_offset[2] = 16384 sbi->s_mb_maxs[2] = 8192
...
ext4_buddy数据结构
struct ext4_buddy {
    //buddy_bitmap的page
	struct page *bd_buddy_page;
    //buddy bitmap的内存区域
	void *bd_buddy;
    //data block bitmap的内存缓存的page
	struct page *bd_bitmap_page;
	void *bd_bitmap;
	struct ext4_group_info *bd_info;
	struct super_block *bd_sb;
	__u16 bd_blkbits;
	ext4_group_t bd_group;
};

ext4_mb_load_buddy函数核心就是初始化ext4_buddy数据结构和bd_sb对应的ext4_sb_info中的s_group_info成员。注意每一个group对应一个ext4_buddy结构体。

buddy bitmap构建过程

ext4_mb_init_group和ext4_mb_load_buddy都会调用ext4_mb_init_cache,我们就以ext4_mb_init_group调用为启动分析。

static noinline_for_stack
int ext4_mb_init_group(struct super_block *sb, ext4_group_t group, gfp_t gfp)
{

	struct ext4_group_info *this_grp;
	struct ext4_buddy e4b;
	struct page *page;
	int ret = 0;

	might_sleep();
	mb_debug(sb, "init group %u\n", group);
	this_grp = ext4_get_group_info(sb, group);
    ...
	ret = ext4_mb_get_buddy_page_lock(sb, group, &e4b, gfp);
    ...
	page = e4b.bd_bitmap_page;
	ret = ext4_mb_init_cache(page, NULL, gfp);
    ...
	/* init buddy cache */
	page = e4b.bd_buddy_page;
    //传入的参数incore是e4b.bd_bitmap是磁盘中读取data block bitmap,通过这个构建buddy bitmap
	ret = ext4_mb_init_cache(page, e4b.bd_bitmap, gfp);
    ...
	return ret;
}

1.ext4_mb_get_buddy_page_lock获取group对应的data block bitmap和buddy bitmap对应的pagecache。然后page会挂在inode的高速缓存address space,这里是哪个inode?linux采用了特殊inode = 2

2.分别调用两次ext4_mb_init_cache初始化刚才创建的page缓存,第一次是data block bitmap,第二次是buddy bitmap。

ext4_mb_get_buddy_page_lock


/*
 * Lock the buddy and bitmap pages. This make sure other parallel init_group
 * on the same buddy page doesn't happen whild holding the buddy page lock.
 * Return locked buddy and bitmap pages on e4b struct. If buddy and bitmap
 * are on the same page e4b->bd_buddy_page is NULL and return value is 0.
 */
static int ext4_mb_get_buddy_page_lock(struct super_block *sb,
		ext4_group_t group, struct ext4_buddy *e4b, gfp_t gfp)
{
	struct inode *inode = EXT4_SB(sb)->s_buddy_cache;
	int block, pnum, poff;
	int blocks_per_page;
	struct page *page;

	e4b->bd_buddy_page = NULL;
	e4b->bd_bitmap_page = NULL;

	blocks_per_page = PAGE_SIZE / sb->s_blocksize;
	/*
	 * the buddy cache inode stores the block bitmap
	 * and buddy information in consecutive blocks.
	 * So for each group we need two blocks.
	 */
	block = group * 2;
	pnum = block / blocks_per_page;
	poff = block % blocks_per_page;
	page = find_or_create_page(inode->i_mapping, pnum, gfp);
	if (!page)
		return -ENOMEM;
	BUG_ON(page->mapping != inode->i_mapping);
	e4b->bd_bitmap_page = page;
	e4b->bd_bitmap = page_address(page) + (poff * sb->s_blocksize);

	if (blocks_per_page >= 2) {
		/* buddy and bitmap are on the same page */
		return 0;
	}

	block++;
	pnum = block / blocks_per_page;
	page = find_or_create_page(inode->i_mapping, pnum, gfp);
	if (!page)
		return -ENOMEM;
	BUG_ON(page->mapping != inode->i_mapping);
	e4b->bd_buddy_page = page;
	return 0;
}

上面函数要注意pnum就是page->index,比如group =0,那么其data block bitmap对应page->index = 0, buddy bitmap对应page->index = 1。find_or_create_page如果已经存在缓存则返回,否则创建。

ext4_mb_init_cache


static int ext4_mb_init_cache(struct page *page, char *incore, gfp_t gfp)
{
	ext4_group_t ngroups;
	int blocksize;
	int blocks_per_page;
	int groups_per_page;
	int err = 0;
	int i;
	ext4_group_t first_group, group;
	int first_block;
	struct super_block *sb;
	struct buffer_head *bhs;
	struct buffer_head **bh = NULL;
	struct inode *inode;
	char *data;
	char *bitmap;
	struct ext4_group_info *grinfo;

	inode = page->mapping->host;
	sb = inode->i_sb;
	ngroups = ext4_get_groups_count(sb);
	blocksize = i_blocksize(inode);
	blocks_per_page = PAGE_SIZE / blocksize;

	mb_debug(sb, "init page %lu\n", page->index);

	groups_per_page = blocks_per_page >> 1;
	if (groups_per_page == 0)
		groups_per_page = 1;

	/* allocate buffer_heads to read bitmaps */
	if (groups_per_page > 1) {
		i = sizeof(struct buffer_head *) * groups_per_page;
		bh = kzalloc(i, gfp);
		if (bh == NULL) {
			err = -ENOMEM;
			goto out;
		}
	} else
		bh = &bhs;

	first_group = page->index * blocks_per_page / 2;

	/* read all groups the page covers into the cache */
	for (i = 0, group = first_group; i < groups_per_page; i++, group++) {
		if (group >= ngroups)
			break;

		grinfo = ext4_get_group_info(sb, group);
		/*
		 * If page is uptodate then we came here after online resize
		 * which added some new uninitialized group info structs, so
		 * we must skip all initialized uptodate buddies on the page,
		 * which may be currently in use by an allocating task.
		 */
		if (PageUptodate(page) && !EXT4_MB_GRP_NEED_INIT(grinfo)) {
			bh[i] = NULL;
			continue;
		}
		bh[i] = ext4_read_block_bitmap_nowait(sb, group, false);
		if (IS_ERR(bh[i])) {
			err = PTR_ERR(bh[i]);
			bh[i] = NULL;
			goto out;
		}
		mb_debug(sb, "read bitmap for group %u\n", group);
	}

	/* wait for I/O completion */
	for (i = 0, group = first_group; i < groups_per_page; i++, group++) {
		int err2;

		if (!bh[i])
			continue;
		err2 = ext4_wait_block_bitmap(sb, group, bh[i]);
		if (!err)
			err = err2;
	}

	first_block = page->index * blocks_per_page;
	for (i = 0; i < blocks_per_page; i++) {
		group = (first_block + i) >> 1;
		if (group >= ngroups)
			break;

		if (!bh[group - first_group])
			/* skip initialized uptodate buddy */
			continue;

		if (!buffer_verified(bh[group - first_group]))
			/* Skip faulty bitmaps */
			continue;
		err = 0;

		/*
		 * data carry information regarding this
		 * particular group in the format specified
		 * above
		 *
		 */
		data = page_address(page) + (i * blocksize);
		bitmap = bh[group - first_group]->b_data;

		/*
		 * We place the buddy block and bitmap block
		 * close together
		 */
		if ((first_block + i) & 1) {
			/* this is block of buddy */
			BUG_ON(incore == NULL);
			mb_debug(sb, "put buddy for group %u in page %lu/%x\n",
				group, page->index, i * blocksize);
			trace_ext4_mb_buddy_bitmap_load(sb, group);
			grinfo = ext4_get_group_info(sb, group);
			grinfo->bb_fragments = 0;
			memset(grinfo->bb_counters, 0,
			       sizeof(*grinfo->bb_counters) *
				(sb->s_blocksize_bits+2));
			/*
			 * incore got set to the group block bitmap below
			 */
			ext4_lock_group(sb, group);
			/* init the buddy */
			memset(data, 0xff, blocksize);
			ext4_mb_generate_buddy(sb, data, incore, group);
			ext4_unlock_group(sb, group);
			incore = NULL;
		} else {
			/* this is block of bitmap */
			BUG_ON(incore != NULL);
			mb_debug(sb, "put bitmap for group %u in page %lu/%x\n",
				group, page->index, i * blocksize);
			trace_ext4_mb_bitmap_load(sb, group);

			/* see comments in ext4_mb_put_pa() */
			ext4_lock_group(sb, group);
			memcpy(data, bitmap, blocksize);

			/* mark all preallocated blks used in in-core bitmap */
			ext4_mb_generate_from_pa(sb, data, group);
			ext4_mb_generate_from_freelist(sb, data, group);
			ext4_unlock_group(sb, group);

			/* set incore so that the buddy information can be
			 * generated using this
			 */
			incore = data;
		}
	}
	SetPageUptodate(page);

out:
	if (bh) {
		for (i = 0; i < groups_per_page; i++)
			brelse(bh[i]);
		if (bh != &bhs)
			kfree(bh);
	}
	return err;
}

读取磁盘中的data block bitmap,初始化刚刚创建的page cache,这个逻辑比较简单,只是将磁盘中的bitmap赋值给page cache。复杂的时候初始化只在内存中的buddy bitmap,这是通过ext4_mb_generate_buddy,这个地方要注意buddy bitmap开始默认都初始化为1,代表占用状态,ext4_mb_generate_buddy通过bd_bitmap构建出来buddy bitmap

 max:group最大的cluster数量(如果block size = cluster size就是block数量)

i = mb_find_next_zero_bit(bitmap, max, 0);根据data block bitmap找到第一个空闲的位置返回给i。

mb_find_next_bit(bitmap, max, i)找到下一给1的bit,那么len = i - first就是一段连续空闲的长度。

ext4_mb_mark_free_simple将这段连续的空闲区域记录到buddy bitmap中。

假设有个block group从129 block之后全部是空闲,ext4_mb_mark_free_simple的执行流程:

32639 chunk = 1
first = 129

第一轮:first = 129 len = 32639 
	bb_counters[0]++
第二轮:   = 130 len = 32638 
	max = ffs(130) - 1 = 1
	min = fls(32638) - 1 = 14
	min = 1; chunk = 1 << min = 2
	
	bb_counters[1]++;
	
第三轮:first = 132 len = 32636
	max = ffs(132) - 1= 2 
	min = fls(32636) - 1= 14
	min = 2; chunk = 1 << min = 4
	bb_counters[2]++;
	
4: first = 136 len = 32632
	max = ffs(136) -1 = 3
	min = fls(32632) - 1=  14
	min = 3 chunk = 1 << 3 = 8
	bb_counters[3]++;
	
5: first = 144 len = 32624
	max = ffs(144) - 1 = 4
	min = fls(32624) - 1= 14
	min = 4 chunk = 16
	bb_counter[4]++
	
6: first = 160 len = 32608
	max = ffs(160) -1 = 5
	min = fls(32608) - 1 = 14
	min = min (max, min) = 5
	chunk = 1 << min = 1 << 5 = 32
	bb_counter[5]++
	
7: fisrt = 192 len = 32576
   max = ffs(192) - 1 = 6
   min = fls(32576) -1 = 14
	min = min(max, min) =6
	chunk = 1 << min = 64
	bb_counters[6]++
	
8: first = 256	len = 32512
	max = ffs(256) - 1 = 8
	min = fls(32512) - 1= 14
	min = min(max, min) = 8
	chunk = 1 << 8 = 256
	bb_counters[8]++
	
9: first = 512 len = 32256
	max = ffs(512) -1 = 9
	min = fls(32256) - 1 = 14
	min = min(max, min) = 9
	chunk = 1 << 9 = 512
	bb_counters[9]++

10: first = 1024 len = 31744
	max = ffs(1024) - 1 = 10
	min = fls(31744) - 1 = 14
	min = min(max, min) = 10
	chunk = 1 << 10 = 1024
	bb_counters[10]++
	
11:	first = 2048 len = 30720
	max = ffs(2048) -1 = 11
	min = fls(30720)-1 = 14
	min = min(max, min) = 11
	chunk  = 1 << 11= 2048
	bb_counters[11]++;
	
12: first = 4096 len = 26624
	max = ffs(4096) - 1 = 12
	min = fls(26624) - 1 = 14
	min = min(max,min) = 12
	chunk = 1 << 12 = 4096
	bb_counters[12]++
	
13: first = 8192 len = 24576
	max = ffs(8192) -1 = 13
	min = fls(24576) -1 = 14
	min = min(max,min) = 13
	chunk = 1 << 13 = 8192
	bb_counters[13]++
	
14: first = 16384 len = 16384
	max = ffs(16384|border) -1 = 13
	min = fls(16384) - 1= 14
	min = min(max, min) = 13
	chunk = 1 << 13 = 8192
	bb_counter[13]++
	
14: first = 24576 len = 8192
	max = ffs(24576|border) -1 = 13
	min = fls(8192) -1 = 13
	min = min(max ,min) = 13
	chunk = 1 << 13 = 8192
	bb_counters[13]++
	
15: first = 32768 len = 0

 最终引用google的一个PPT中图示 :

 

参考文章:

关于ext4 buddy bitmap构建分析_ext4 ext4_buddy_五年一剑的博客-CSDN博客

https://www.cnblogs.com/kanie/p/15359346.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ext4 mballoc之buddy算法 的相关文章

  • 在Linux上编译C# + WPF以便在Windows上运行

    我有一个 C 应用程序 其中某些部分是使用 WPF 编写的 Mono 不支持 可以在 Linux 上编译这个应用程序吗 最终 该应用程序将在 Windows 上运行 但它是更大框架的一部分 并且我们的整个构建过程在 Linux 上运行 因此
  • 拆分字符串以仅获取前 5 个字符

    我想去那个地点 var log src ap kernelmodule 10 001 100 但看起来我的代码必须处理 ap kernelmodule 10 002 100 ap kernelmodule 10 003 101 等 我想使用
  • 在 Linux 上更快地分叉大型进程?

    在现代 Linux 上达到与 Linux 相同效果的最快 最好的方法是什么 fork execve combo 从一个大的过程 我的问题是进程分叉大约 500MByte 大 并且一个简单的基准测试只能从进程中实现约 50 个分叉 秒 比较最
  • awk 子串单个字符

    这是columns txt aaa bbb 3 ccc ddd 2 eee fff 1 3 3 g 3 hhh i jjj 3 kkk ll 3 mm nn oo 3 我可以找到第二列以 b 开头的行 awk if substr 2 1 1
  • 如何通过替换为空页映射来取消映射 mmap 文件

    Linux 用户空间有没有办法用空页面 映射自 dev null 或者可能是一个空页面 重复映射到从文件映射的页面的顶部 对于上下文 我想找到这个 JDK bug 的修复 https bugs openjdk java net browse
  • 如何禁用 GNOME 桌面屏幕锁定? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 如何阻止 GNOME 桌面在几分钟空闲时间后锁定屏幕 我已经尝试过官方手册了在红帽 https access redhat com doc
  • nginx 上的多个网站和可用网站

    通过 nginx 的基本安装 您的sites available文件夹只有一个文件 default 怎么样sites available文件夹的工作原理以及如何使用它来托管多个 单独的 网站 只是为了添加另一种方法 您可以为您托管的每个虚拟
  • 我可以从命令行打印 html 文件(带有图像、css)吗?

    我想从脚本中打印带有图像的样式化 html 页面 谁能建议一个开源解决方案 我使用的是 Linux Ubuntu 8 04 但也对其他操作系统的解决方案感兴趣 你可以给html2ps http user it uu se jan html2
  • 无法从 jenkins 作为后台进程运行 nohup 命令

    更新 根据下面的讨论 我编辑了我的答案以获得更准确的描述 我正在尝试从詹金斯运行 nohup 命令 完整的命令是 nohup java jar home jar server process 0 35 jar prod gt gt var
  • Linux中的定时器类

    我需要一个计时器来以相对较低的分辨率执行回调 在 Linux 中实现此类 C 计时器类的最佳方法是什么 有我可以使用的库吗 如果您在框架 Glib Qt Wx 内编写 那么您已经拥有一个具有定时回调功能的事件循环 我认为情况并非如此 如果您
  • sendfile64 只复制约2GB

    我需要使用 sendfile64 复制大约 16GB 的文件 到目前为止我所取得的成就是 include
  • 所有平台上的java

    如果您想用 java 为 Windows Mac 和 Linux 编写桌面应用程序 那么所有这些代码都相同吗 您只需更改 GUI 即可使 Windows 应用程序更像 Windows 等等 如果不深入细节 它是如何工作的 Java 的卖点之
  • 如何有效截断文件头?

    大家都知道truncate file size 函数 通过截断文件尾部将文件大小更改为给定大小 但是如何做同样的事情 只截断文件的尾部和头部呢 通常 您必须重写整个文件 最简单的方法是跳过前几个字节 将其他所有内容复制到临时文件中 并在完成
  • 添加要在给定命令中运行的 .env 变量

    我有一个 env 文件 其中包含如下变量 HELLO world SOMETHING nothing 前几天我发现了这个很棒的脚本 它将这些变量放入当前会话中 所以当我运行这样的东西时 cat env grep v xargs node t
  • arm64和armhf有什么区别?

    Raspberry Pi Type 3 具有 64 位 CPU 但其架构不是arm64 but armhf 有什么区别arm64 and armhf armhf代表 arm hard float 是给定的名称Debian 端口 https
  • 如何在 Linux shell 中将十六进制转换为 ASCII 字符?

    假设我有一个字符串5a 这是 ASCII 字母的十六进制表示Z 我需要找到一个 Linux shell 命令 它将接受一个十六进制字符串并输出该十六进制字符串代表的 ASCII 字符 所以如果我这样做 echo 5a command im
  • 两种情况或 if 哪个更快? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我必须制作一个 非常 轻的脚本 它将接受用户的选项并调用脚本中的函数来执行一些任务 现在我可以使用 IF 和 CASE 选项 但我想知道两
  • 将 PDF 转换为 600dpi 的 TIFF 和 jpg 96 dpi

    我想使用 ImageMagick 从 Python 脚本将 pdf 转换为 600 dpi 的 tiff 和 96 dpi 的 jpg 我使用 imagemagick 命令行完成了这项任务 但我想使用python中的Imagemagick将
  • 使用 sh 运行 bash 脚本

    我有 bash 脚本 它需要 bash 另一个人尝试运行它 sh script name sh 它失败了 因为 sh 是他的发行版中 dash 的符号链接 ls la bin sh lrwxrwxrwx 1 root root 4 Aug
  • 有谁知道在哪里定义硬件、版本和序列号。 /proc/cpuinfo 的字段?

    我想确保我的 proc cpuinfo 是准确的 目前它输出 Hardware am335xevm Revision 0000 Serial 0000000000000000 我可以在代码中的哪里更改它以给出实际值 这取决于 Linux 的

随机推荐

  • nginx之proxy_pass代理后端https请求

    本文转载自 https my oschina net foreverich blog 1517128 前言本文解释了怎么对nginx和后端服务器组或代理服务器进行加密http通信 内容提纲前提条件获取SSL服务端证书获取SSL客户端证书配置
  • MySQL Error Code: 2013. Lost connection to MySQL server during query解决

    如果你出现了这个问题 先尝试判断你是哪种情况 你的SQL语句需要执行很久 超过默认的时长 gt 方案1 你的SQL语句很简单 但就是执行不了 gt 方案2 解决方法1 尝试打开设置调整超时时间后重试 解决方法2 如果你在尝试修改空表都发生了
  • 2. Java枚举(enum)

    Java枚举是一个特殊的类 一般表示一组常量 使用enum关键字来定义 各个常量使用逗号 来分割 实例 public enum BizErrorInfo USER NOT FOUND codeValue 1004 message 用户不存在
  • Springboot +mybatis-plus 实现公共字段自动填充

    本文讲述了在SpringBoot 中使用Mybatis Plus如何实现一个自动填充功能 目录 一 应用场景 二 代码实现步骤 1 建数据库表 t user 2 创建spring boot项目集成mybatis plus实现字段自动填充 2
  • 少儿机器人编程主要使用的语言有啥

    少儿机器人编程主要使用的语言 说起孩子的学习 想必家长们都是非常的有发言权的 很多的家长在培养孩子的学习方面也可以说相当的耐心的 他们会给孩子选择一些能够有利于孩子成长的课程 就拿现在很多的家长想要孩子去学习机器人编程的课程来说 有的家长对
  • PHP开源大全

    WordPress PHP开源 博客Blog WordPress是最热门的开源个人信息发布系统 Blog 之一 基于PHP MySQL构建 WordPress提供的功能包括 1 文章发布 分类 归档 2 提供文章 评论 分类等多种形式的RS
  • MySQL数据库数据导出出现1290(secure_file_priv)错误解决方法

    目录 解决方案 测试效果 解决方案 secure file priv是用来限制mysql数据库导出的位置 目录 算是一直安全保护系统 我们可以去通过show variables like secure 这个指令去查看secure file
  • 2021-05-08记录一次最新版小红书逆向细节

    预备工具 ida7 5 piexl 手机 jadx jeb 某书是有TracerPid反调试 先过反调试 这有两个方法 1 Frida hook fopen 过滤 2 修改安卓源码去掉TracerPid 1 Frida hook脚本 fun
  • Python入门到实战(十一)无监督学习、KMeans、KNN、实现图像分割、监督学习VS无监督学习

    Python入门到实战 十一 无监督学习 KMeans KNN 实现图像分割 监督学习VS无监督学习 无监督学习unsupervised learning 特点 应用 K均值聚类 核心流程 核心公式 KMeans VS KNN 实战 KMe
  • 深度遍历 和 广度遍历

    深度dfs 用到了递归 先把根节点 输出根节点 然后遍历根节点的孩子 const fun1 root gt console log root val root children forEach fun1 fun1 tree 广度遍历 每次遍
  • java 集成MinIo

    1 引入maven包 注意jar包冲突
  • 在springboot打包成jar后,无法读取自定义文件的解决办法

    前两天在做springcloud框架下的项目的时候 用到有一个框架之外的文件需要进行读取 当时在eclipse中编码时通过this getClass getResource来获取文件的路径 没有任何的问题 但是在打成jar以后 这是是打成j
  • c++3之static、const、friend关键字

    1 1static 修饰局部变量 延长生命周期 由栈区 gt 静态区 修饰全局变量或函数 限制作用域 只能用于本文件中使用 static 成员变量 1 static成员变量不占class的空间 修饰成员变量 需要在外部单独定义 要加来源 A
  • Think-on-Graph: Deep and Responsible Reasoning of Large Language Model with Knowledge Graph

    本文是LLM系列文章 针对 Think on Graph Deep and Responsible Reasoning of Large Language Model with Knowledge Graph 的翻译 对图的思考 基于知识图
  • TensorFlow时间序列tfts-seq2seq

    关注我的公众号YueTan进行交流探讨 欢迎关注时间序列仓库 https github com LongxingTan Time series prediction 时间序列1 概述 时间序列2 transformers 时间序列3 seq
  • Windows11 安卓子系统安装(附apk安装步骤)

    Windows11 安卓子系统安装 附apk安装步骤 系列 Android 前言 Win11安卓子系统 Windows Subsystem for Android 是一个组件 以帮助通过亚马逊商店在其上运行Android 应用程序 在最新的
  • Golang适合高并发场景的原因分析

    典型的两个现实案例 我们先看两个用Go做消息推送的案例实际处理能力 360消息推送的数据 16台机器 标配 24个硬件线程 64GB内存 Linux Kernel 2 6 32 x86 64 单机80万并发连接 load 0 2 0 4 C
  • VBA-选择文件对话框

    打开选择路径对话框 strTitle 对话框标题名 strTypesDec 选择文件类型名 多文件名时用 连接 Images All files strExten 选择文件类型 一个文件名有多个读取类型时用 连接 多个文件名用 连接 gif
  • c++ extern的用处(转载)

    转自chao yu cnblog com 1 基本解释 extern可以置于变量或者函数前 以标示变量或者函数的定义在别的文件中 提示编译器遇到此变量和函数时在其他模块中寻找其定义 此外extern也可用来进行链接指定 也就是说extern
  • ext4 mballoc之buddy算法

    buddy bitmap 根据 Ext4文件系统介绍 理论篇 nginux的博客 CSDN博客 我们知道磁盘上有1block 大小 默认4K data block bitmap 每bit位代表一个block的使用情况 1代表占用 0代表空闲