w_stacks> stacks_7000.txt
	cat stacks_7000.txt
	 post_alloc_hook+0x177/0x1a0
	 get_page_from_freelist+0xd01/0xd80
	 __alloc_pages+0x39e/0x7e0
	 alloc_pages_mpol+0x22e/0x490
	 folio_alloc+0xd5/0x110
	 filemap_alloc_folio+0x78/0x230
	 page_cache_ra_order+0x287/0x6f0
	 filemap_get_pages+0x517/0x1160
	 filemap_read+0x304/0x9f0
	 xfs_file_buffered_read+0xe6/0x1d0 [xfs]
	 xfs_file_read_iter+0x1f0/0x380 [xfs]
	 __kernel_read+0x3b9/0x730
	 kernel_read_file+0x309/0x4d0
	 __do_sys_finit_module+0x381/0x730
	 do_syscall_64+0x8d/0x150
	 entry_SYSCALL_64_after_hwframe+0x62/0x6a
	nr_base_pages: 20824
	...

	cat /sys/kernel/debug/page_owner > page_owner_full.txt
	./page_owner_sort page_owner_full.txt sorted_page_owner.txt

   ``page_owner_full.txt`` 的一般输出情况如下::

	Page allocated via order XXX, ...
	PFN XXX ...
	// 栈详情

	Page allocated via order XXX, ...
	PFN XXX ...
	// 栈详情
    默认情况下，它将以一个给定的pfn开始，做完整的pfn转储，且page_owner支持fseek。

    FILE *fp = fopen("/sys/kernel/debug/page_owner", "r");
    fseek(fp, pfn_start, SEEK_SET);

   ``page_owner_sort`` 工具忽略了 ``PFN`` 行，将剩余的行放在buf中，使用regexp提
   取页序值，计算buf的次数和页数，最后根据参数进行排序。

   在 ``sorted_page_owner.txt`` 中可以看到关于谁分配了每个页面的结果。一般输出::

	XXX times, XXX pages:
	Page allocated via order XXX, ...
	// Detailed stack

   默认情况下， ``page_owner_sort`` 是根据buf的时间来排序的。如果你想
   按buf的页数排序，请使用-m参数。详细的参数是:

   基本函数::

	排序:
		-a		按内存分配时间排序
		-m		按总内存排序
		-p		按pid排序。
		-P		按tgid排序。
		-n		按任务命令名称排序。
		-r		按内存释放时间排序。
		-s		按堆栈跟踪排序。
		-t		按时间排序（默认）。
       --sort <order> 指定排序顺序。排序的语法是[+|-]key[,[+|-]key[,...]]。从
       **标准格式指定器**那一节选择一个键。"+"是可选的，因为默认的方向是数字或
       词法的增加。允许混合使用缩写和完整格式的键。

        例子:
				./page_owner_sort <input> <output> --sort=n,+pid,-tgid
				./page_owner_sort <input> <output> --sort=at

    其它函数::

	剔除:
		--cull <rules>
		        指定剔除规则。剔除的语法是key[,key[,...]]。从**标准格式指定器**
				部分选择一个多字母键。
		<rules>是一个以逗号分隔的列表形式的单一参数，它提供了一种指定单个剔除规则的
		方法。 识别的关键字在下面的**标准格式指定器**部分有描述。<规则>可以通过键的
		序列k1,k2,...来指定，在下面的标准排序键部分有描述。允许混合使用简写和完整形
		式的键。

		Examples:
				./page_owner_sort <input> <output> --cull=stacktrace
				./page_owner_sort <input> <output> --cull=st,pid,name
				./page_owner_sort <input> <output> --cull=n,f

	过滤:
		-f		过滤掉内存已被释放的块的信息。

	选择:
		--pid <pidlist>		按pid选择。这将选择进程ID号出现在<pidlist>中的块。
		--tgid <tgidlist>	按tgid选择。这将选择其线程组ID号出现在<tgidlist>
		                    中的块。
		--name <cmdlist>	按任务命令名称选择。这将选择其任务命令名称出现在
		                    <cmdlist>中的区块。

		<pidlist>, <tgidlist>, <cmdlist>是以逗号分隔的列表形式的单个参数，
		它提供了一种指定单个选择规则的方法。


		例子:
				./page_owner_sort <input> <output> --pid=1
				./page_owner_sort <input> <output> --tgid=1,2,3
				./page_owner_sort <input> <output> --name name1,name2

标准格式指定器
==============
::

  --sort的选项:

	短键		长键		描述
	p		pid		进程ID
	tg		tgid		线程组ID
	n		name		任务命令名称
	st		stacktrace	页面分配的堆栈跟踪
	T		txt		块的全文
	ft		free_ts		页面释放时的时间戳
	at		alloc_ts	页面被分配时的时间戳
	ator		allocator	页面的内存分配器

  --curl的选项:

	短键		长键		描述
	p		pid		进程ID
	tg		tgid		线程组ID
	n		name		任务命令名称
	f		free		该页是否已经释放
	st		stacktrace	页面分配的堆栈跟踪
	ator		allocator	页面的内存分配器
