前面已经分析了内存管理框架的构建实现过程,有部分内容未完全呈现出来,这里主要做个补充。

如下图,这是前面已经看到过的linux物理内存管理框架的层次关系。

现着重分析一下各个管理结构体的成员功能作用。

  1. file:/include/linux/mmzone.h
  2. typedef struct pglist_data {
  3. struct zone node_zones[MAX_NR_ZONES];
  4. struct zonelist node_zonelists[MAX_ZONELISTS];
  5. int nr_zones;
  6. #ifdef CONFIG_FLAT_NODE_MEM_MAP /* means !SPARSEMEM */
  7. struct page *node_mem_map;
  8. #ifdef CONFIG_MEMCG
  9. struct page_cgroup *node_page_cgroup;
  10. #endif
  11. #endif
  12. #ifndef CONFIG_NO_BOOTMEM
  13. struct bootmem_data *bdata;
  14. #endif
  15. #ifdef CONFIG_MEMORY_HOTPLUG
  16. /*
  17. * Must be held any time you expect node_start_pfn, node_present_pages
  18. * or node_spanned_pages stay constant. Holding this will also
  19. * guarantee that any pfn_valid() stays that way.
  20. *
  21. * pgdat_resize_lock() and pgdat_resize_unlock() are provided to
  22. * manipulate node_size_lock without checking for CONFIG_MEMORY_HOTPLUG.
  23. *
  24. * Nests above zone->lock and zone->span_seqlock
  25. */
  26. spinlock_t node_size_lock;
  27. #endif
  28. unsigned long node_start_pfn;
  29. unsigned long node_present_pages; /* total number of physical pages */
  30. unsigned long node_spanned_pages; /* total size of physical page
  31. range, including holes */
  32. int node_id;
  33. nodemask_t reclaim_nodes; /* Nodes allowed to reclaim from */
  34. wait_queue_head_t kswapd_wait;
  35. wait_queue_head_t pfmemalloc_wait;
  36. struct task_struct *kswapd; /* Protected by lock_memory_hotplug() */
  37. int kswapd_max_order;
  38. enum zone_type classzone_idx;
  39. #ifdef CONFIG_NUMA_BALANCING
  40. /* Lock serializing the migrate rate limiting window */
  41. spinlock_t numabalancing_migrate_lock;
  42. /* Rate limiting time interval */
  43. unsigned long numabalancing_migrate_next_window;
  44. /* Number of pages migrated during the rate limiting time interval */
  45. unsigned long numabalancing_migrate_nr_pages;
  46. #endif
  47. } pg_data_t;
  • struct zone node_zones[MAX_NR_ZONES];

——存放该pg_data_t里面的zone;

  • struct zonelist node_zonelists[MAX_ZONELISTS];

——其指向一个page结构的数组,数组中的每个成员为该节点中的一个物理页面,于是整个数组就对应了该节点中所有的物理页面;

  • struct page_cgroup *node_page_cgroup;

——用于管理page_cgroup,原来的page_cgroup是page页面管理结构的一个成员,现在移到这里了,它将会在初始化时所有的page_cgroup都将申请下来;

  • struct bootmem_data *bdata;

——该数据指向bootmem_node_data,可以通过system.map查到。原是用于bootmem内存分配器的信息存储,当前改用memblock算法,则不存在该成员;

  • unsigned long node_start_pfn;

——指向当前pg_data_t结构管理的物理起始页面;

  • unsigned long node_present_pages;

——记录物理页面数总量,除开内存空洞的物理页面数;

  • unsigned long node_spanned_pages;

——最大和最小页面号的差值,包括内存空洞的总的物理页面大小;

  • int node_id;

——pg_data_t对应的索引号,非NUMA架构下该值为0;

  • nodemask_t reclaim_nodes;

——用于记录可回收的内存管理节点node信息;

  • wait_queue_head_t kswapd_wait;

——kswapd是页面交换守护线程,该线程会阻塞在这个等待队列,当满足条件后,调用wake_up_interruptible()唤醒该队列进行相关操作;

  • wait_queue_head_t pfmemalloc_wait;

——用于减缓内存直接回收;

  • struct task_struct *kswapd;

——指向kswapd守护线程的任务指针;

  • int kswapd_max_order;

——用于表示kswapd守护线程每次回收的页面个数;

  • enum zone_type classzone_idx;

——该成员与kswapd有关;

  1. file:/include/linux/mmzone.h
  2. struct zone {
  3. /* Fields commonly accessed by the page allocator */
  4. /* zone watermarks, access with *_wmark_pages(zone) macros */
  5. unsigned long watermark[NR_WMARK];
  6. /*
  7. * When free pages are below this point, additional steps are taken
  8. * when reading the number of free pages to avoid per-cpu counter
  9. * drift allowing watermarks to be breached
  10. */
  11. unsigned long percpu_drift_mark;
  12. /*
  13. * We don't know if the memory that we're going to allocate will be freeable
  14. * or/and it will be released eventually, so to avoid totally wasting several
  15. * GB of ram we must reserve some of the lower zone memory (otherwise we risk
  16. * to run OOM on the lower zones despite there's tons of freeable ram
  17. * on the higher zones). This array is recalculated at runtime if the
  18. * sysctl_lowmem_reserve_ratio sysctl changes.
  19. */
  20. unsigned long lowmem_reserve[MAX_NR_ZONES];
  21. /*
  22. * This is a per-zone reserve of pages that should not be
  23. * considered dirtyable memory.
  24. */
  25. unsigned long dirty_balance_reserve;
  26. #ifdef CONFIG_NUMA
  27. int node;
  28. /*
  29. * zone reclaim becomes active if more unmapped pages exist.
  30. */
  31. unsigned long min_unmapped_pages;
  32. unsigned long min_slab_pages;
  33. #endif
  34. struct per_cpu_pageset __percpu *pageset;
  35. /*
  36. * free areas of different sizes
  37. */
  38. spinlock_t lock;
  39. #if defined CONFIG_COMPACTION || defined CONFIG_CMA
  40. /* Set to true when the PG_migrate_skip bits should be cleared */
  41. bool compact_blockskip_flush;
  42. /* pfns where compaction scanners should start */
  43. unsigned long compact_cached_free_pfn;
  44. unsigned long compact_cached_migrate_pfn;
  45. #endif
  46. #ifdef CONFIG_MEMORY_HOTPLUG
  47. /* see spanned/present_pages for more description */
  48. seqlock_t span_seqlock;
  49. #endif
  50. struct free_area free_area[MAX_ORDER];
  51. #ifndef CONFIG_SPARSEMEM
  52. /*
  53. * Flags for a pageblock_nr_pages block. See pageblock-flags.h.
  54. * In SPARSEMEM, this map is stored in struct mem_section
  55. */
  56. unsigned long *pageblock_flags;
  57. #endif /* CONFIG_SPARSEMEM */
  58. #ifdef CONFIG_COMPACTION
  59. /*
  60. * On compaction failure, 1<<compact_defer_shift compactions
  61. * are skipped before trying again. The number attempted since
  62. * last failure is tracked with compact_considered.
  63. */
  64. unsigned int compact_considered;
  65. unsigned int compact_defer_shift;
  66. int compact_order_failed;
  67. #endif
  68. ZONE_PADDING(_pad1_)
  69. /* Fields commonly accessed by the page reclaim scanner */
  70. spinlock_t lru_lock;
  71. struct lruvec lruvec;
  72. unsigned long pages_scanned; /* since last reclaim */
  73. unsigned long flags; /* zone flags, see below */
  74. /* Zone statistics */
  75. atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS];
  76. /*
  77. * The target ratio of ACTIVE_ANON to INACTIVE_ANON pages on
  78. * this zone's LRU. Maintained by the pageout code.
  79. */
  80. unsigned int inactive_ratio;
  81. ZONE_PADDING(_pad2_)
  82. /* Rarely used or read-mostly fields */
  83. /*
  84. * wait_table -- the array holding the hash table
  85. * wait_table_hash_nr_entries -- the size of the hash table array
  86. * wait_table_bits -- wait_table_size == (1 << wait_table_bits)
  87. *
  88. * The purpose of all these is to keep track of the people
  89. * waiting for a page to become available and make them
  90. * runnable again when possible. The trouble is that this
  91. * consumes a lot of space, especially when so few things
  92. * wait on pages at a given time. So instead of using
  93. * per-page waitqueues, we use a waitqueue hash table.
  94. *
  95. * The bucket discipline is to sleep on the same queue when
  96. * colliding and wake all in that wait queue when removing.
  97. * When something wakes, it must check to be sure its page is
  98. * truly available, a la thundering herd. The cost of a
  99. * collision is great, but given the expected load of the
  100. * table, they should be so rare as to be outweighed by the
  101. * benefits from the saved space.
  102. *
  103. * __wait_on_page_locked() and unlock_page() in mm/filemap.c, are the
  104. * primary users of these fields, and in mm/page_alloc.c
  105. * free_area_init_core() performs the initialization of them.
  106. */
  107. wait_queue_head_t * wait_table;
  108. unsigned long wait_table_hash_nr_entries;
  109. unsigned long wait_table_bits;
  110. /*
  111. * Discontig memory support fields.
  112. */
  113. struct pglist_data *zone_pgdat;
  114. /* zone_start_pfn == zone_start_paddr >> PAGE_SHIFT */
  115. unsigned long zone_start_pfn;
  116. /*
  117. * spanned_pages is the total pages spanned by the zone, including
  118. * holes, which is calculated as:
  119. * spanned_pages = zone_end_pfn - zone_start_pfn;
  120. *
  121. * present_pages is physical pages existing within the zone, which
  122. * is calculated as:
  123. * present_pages = spanned_pages - absent_pages(pages in holes);
  124. *
  125. * managed_pages is present pages managed by the buddy system, which
  126. * is calculated as (reserved_pages includes pages allocated by the
  127. * bootmem allocator):
  128. * managed_pages = present_pages - reserved_pages;
  129. *
  130. * So present_pages may be used by memory hotplug or memory power
  131. * management logic to figure out unmanaged pages by checking
  132. * (present_pages - managed_pages). And managed_pages should be used
  133. * by page allocator and vm scanner to calculate all kinds of watermarks
  134. * and thresholds.
  135. *
  136. * Locking rules:
  137. *
  138. * zone_start_pfn and spanned_pages are protected by span_seqlock.
  139. * It is a seqlock because it has to be read outside of zone->lock,
  140. * and it is done in the main allocator path. But, it is written
  141. * quite infrequently.
  142. *
  143. * The span_seq lock is declared along with zone->lock because it is
  144. * frequently read in proximity to zone->lock. It's good to
  145. * give them a chance of being in the same cacheline.
  146. *
  147. * Write access to present_pages at runtime should be protected by
  148. * lock_memory_hotplug()/unlock_memory_hotplug(). Any reader who can't
  149. * tolerant drift of present_pages should hold memory hotplug lock to
  150. * get a stable value.
  151. *
  152. * Read access to managed_pages should be safe because it's unsigned
  153. * long. Write access to zone->managed_pages and totalram_pages are
  154. * protected by managed_page_count_lock at runtime. Idealy only
  155. * adjust_managed_page_count() should be used instead of directly
  156. * touching zone->managed_pages and totalram_pages.
  157. */
  158. unsigned long spanned_pages;
  159. unsigned long present_pages;
  160. unsigned long managed_pages;
  161. /*
  162. * Number of MIGRATE_RESEVE page block. To maintain for just
  163. * optimization. Protected by zone->lock.
  164. */
  165. int nr_migrate_reserve_block;
  166. /*
  167. * rarely used fields:
  168. */
  169. const char *name;
  170. } ____cacheline_internodealigned_in_smp;
  • unsigned long watermark[NR_WMARK];

——该数组有三个值WMARK_MIN、WMARK_LOW、WMARK_HIGH,如命名所标识,min最小,low居中,high最大。内存分配过程中,当空闲页面达到low时,内存分配器会唤醒kswapd守护进程来回收物理页面;当空闲页面达到min时,内存分配器就会唤醒kswapd以同步方式回收;如果kswapd被唤醒后,空闲页面达到high时,则会使kswapd再次休眠;

  • unsigned long percpu_drift_mark;

——当空闲页面低于该值,将会引发附加操作的执行,用于避免前面的watermark被冲破;

  • unsigned long lowmem_reserve[MAX_NR_ZONES];

——记录每个管理区中必须保留的物理页面数,以用于紧急状况下的内存分配;

  • unsigned long dirty_balance_reserve;

——用于表示不会被内存分配器分配出去的空闲页面部分的近似值;

  • struct per_cpu_pageset __percpu *pageset;

——该数组里面的成员pcp用于实现冷热页面的管理;

  • spinlock_t lock;

——spinlock锁,用于解决该管理区的并发问题;

  • struct free_area free_area[MAX_ORDER];

——主要用于Buddy内存管理算法(伙伴算法);

  • unsigned long *pageblock_flags;

——与伙伴算法的碎片迁移算法有关;

  • spinlock_t lru_lock;

——用于保护lruvec结构数据;

  • struct lruvec lruvec;

——lruvec该数组里面有一个lists是用于lru管理的链表,另外有一个reclaim_stat用于页面回收的状态标示;

  • unsigned long pages_scanned;

——用于记录上次物理页面回收时,扫描过的页描述符总数;

  • unsigned long flags;

——用于表示当前内存管理区的状态;

  • atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS];

——用于统计该内存管理区中各项状态的数值;

  • unsigned int inactive_ratio;

——不活跃的页面比例;

  • wait_queue_head_t *wait_table;

  • unsigned long wait_table_hash_nr_entries;

  • unsigned long wait_table_bits;

  • struct pglist_data *zone_pgdat;

——指向该内存管理区的pg_data_list;

  • unsigned long zone_start_pfn;

——记录当前内存管理区中最小的物理页面号;

  • unsigned long spanned_pages;

——记录内存管理区的总页面数,包括内存空洞的页面数,实则上是管理区末尾页面号和起始页面号的差值;

  • unsigned long present_pages;

——除去内存空洞后的内存管理区实际有效的总页面数;

  • unsigned long managed_pages;

——用于记录被内存管理算法管理的物理页面数,这是除去了在初始化阶段被申请的页面;

  • int nr_migrate_reserve_block;

——用于优化的,记录内存迁移保留的页面数;

  • const char *name;

——用于记录该管理区的名字;

  1. file:/include/linux/mmzone.h
  2. /*
  3. * Each physical page in the system has a struct page associated with
  4. * it to keep track of whatever it is we are using the page for at the
  5. * moment. Note that we have no way to track which tasks are using
  6. * a page, though if it is a pagecache page, rmap structures can tell us
  7. * who is mapping it.
  8. *
  9. * The objects in struct page are organized in double word blocks in
  10. * order to allows us to use atomic double word operations on portions
  11. * of struct page. That is currently only used by slub but the arrangement
  12. * allows the use of atomic double word operations on the flags/mapping
  13. * and lru list pointers also.
  14. */
  15. struct page {
  16. /* First double word block */
  17. unsigned long flags; /* Atomic flags, some possibly
  18. * updated asynchronously */
  19. union {
  20. struct address_space *mapping; /* If low bit clear, points to
  21. * inode address_space, or NULL.
  22. * If page mapped as anonymous
  23. * memory, low bit is set, and
  24. * it points to anon_vma object:
  25. * see PAGE_MAPPING_ANON below.
  26. */
  27. void *s_mem; /* slab first object */
  28. };
  29. /* Second double word */
  30. struct {
  31. union {
  32. pgoff_t index; /* Our offset within mapping. */
  33. void *freelist; /* sl[aou]b first free object */
  34. bool pfmemalloc; /* If set by the page allocator,
  35. * ALLOC_NO_WATERMARKS was set
  36. * and the low watermark was not
  37. * met implying that the system
  38. * is under some pressure. The
  39. * caller should try ensure
  40. * this page is only used to
  41. * free other pages.
  42. */
  43. };
  44. union {
  45. #if defined(CONFIG_HAVE_CMPXCHG_DOUBLE) && \
  46. defined(CONFIG_HAVE_ALIGNED_STRUCT_PAGE)
  47. /* Used for cmpxchg_double in slub */
  48. unsigned long counters;
  49. #else
  50. /*
  51. * Keep _count separate from slub cmpxchg_double data.
  52. * As the rest of the double word is protected by
  53. * slab_lock but _count is not.
  54. */
  55. unsigned counters;
  56. #endif
  57. struct {
  58. union {
  59. /*
  60. * Count of ptes mapped in
  61. * mms, to show when page is
  62. * mapped & limit reverse map
  63. * searches.
  64. *
  65. * Used also for tail pages
  66. * refcounting instead of
  67. * _count. Tail pages cannot
  68. * be mapped and keeping the
  69. * tail page _count zero at
  70. * all times guarantees
  71. * get_page_unless_zero() will
  72. * never succeed on tail
  73. * pages.
  74. */
  75. atomic_t _mapcount;
  76. struct { /* SLUB */
  77. unsigned inuse:16;
  78. unsigned objects:15;
  79. unsigned frozen:1;
  80. };
  81. int units; /* SLOB */
  82. };
  83. atomic_t _count; /* Usage count, see below. */
  84. };
  85. unsigned int active; /* SLAB */
  86. };
  87. };
  88. /* Third double word block */
  89. union {
  90. struct list_head lru; /* Pageout list, eg. active_list
  91. * protected by zone->lru_lock !
  92. */
  93. struct { /* slub per cpu partial pages */
  94. struct page *next; /* Next partial slab */
  95. #ifdef CONFIG_64BIT
  96. int pages; /* Nr of partial slabs left */
  97. int pobjects; /* Approximate # of objects */
  98. #else
  99. short int pages;
  100. short int pobjects;
  101. #endif
  102. };
  103. struct list_head list; /* slobs list of pages */
  104. struct slab *slab_page; /* slab fields */
  105. struct rcu_head rcu_head; /* Used by SLAB
  106. * when destroying via RCU
  107. */
  108. #if defined(CONFIG_TRANSPARENT_HUGEPAGE) && USE_SPLIT_PMD_PTLOCKS
  109. pgtable_t pmd_huge_pte; /* protected by page->ptl */
  110. #endif
  111. };
  112. /* Remainder is not double word aligned */
  113. union {
  114. unsigned long private; /* Mapping-private opaque data:
  115. * usually used for buffer_heads
  116. * if PagePrivate set; used for
  117. * swp_entry_t if PageSwapCache;
  118. * indicates order in the buddy
  119. * system if PG_buddy is set.
  120. */
  121. #if USE_SPLIT_PTE_PTLOCKS
  122. #if ALLOC_SPLIT_PTLOCKS
  123. spinlock_t *ptl;
  124. #else
  125. spinlock_t ptl;
  126. #endif
  127. #endif
  128. struct kmem_cache *slab_cache; /* SL[AU]B: Pointer to slab */
  129. struct page *first_page; /* Compound tail pages */
  130. };
  131. /*
  132. * On machines where all RAM is mapped into kernel address space,
  133. * we can simply calculate the virtual address. On machines with
  134. * highmem some memory is mapped into kernel virtual memory
  135. * dynamically, so we need a place to store that address.
  136. * Note that this field could be 16 bits on x86 ... ;)
  137. *
  138. * Architectures with slow multiplication can define
  139. * WANT_PAGE_VIRTUAL in asm/page.h
  140. */
  141. #if defined(WANT_PAGE_VIRTUAL)
  142. void *virtual; /* Kernel virtual address (NULL if
  143. not kmapped, ie. highmem) */
  144. #endif /* WANT_PAGE_VIRTUAL */
  145. #ifdef CONFIG_WANT_PAGE_DEBUG_FLAGS
  146. unsigned long debug_flags; /* Use atomic bitops on this */
  147. #endif
  148. #ifdef CONFIG_KMEMCHECK
  149. /*
  150. * kmemcheck wants to track the status of each byte in a page; this
  151. * is a pointer to such a status block. NULL if not tracked.
  152. */
  153. void *shadow;
  154. #endif
  155. #ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS
  156. int _last_cpupid;
  157. #endif
  158. }

(该结构很多union结构,主要是用于各种算法不同数据的空间复用,暂时记录部分常见的数据成员)

  • unsigned long flags;

——用于记录页框的类型;

  • struct address_space *mapping;

——用于区分该页是映射页框还是匿名页框;

  • atomic_t _mapcount;

——记录了系统中页表有多少项指向该页;

  • atomic_t _count;

——当前系统对该页面的引用次数;

  • struct list_head lru;

——当页框处于分配状态时,该成员用于zone的lruvec里面的list,当页框未被分配时则用于伙伴算法;

  • unsigned long private;

——指向“私有”数据的指针。根据页的用途,可以用不同的方式使用该指针,通常用于与数据缓冲区关联起来;

  • void *virtual;

——用于高端内存区域的页,即用于无法直接映射的页,该成员用于存储该页的虚拟地址;

Linux-3.14.12内存管理笔记【构建内存管理框架(5)】的更多相关文章

  1. Linux-3.14.12内存管理笔记【内存泄漏检测kmemleak示例】【转】

    本文转载自:http://blog.chinaunix.net/uid-26859697-id-5758037.html 分析完kmemleak实现后,照常实验一下,以确定功能正常. 如kmemche ...

  2. Linux中的Buffer Cache和Page Cache echo 3 > /proc/sys/vm/drop_caches Slab内存管理机制 SLUB内存管理机制

    Linux中的Buffer Cache和Page Cache echo 3 > /proc/sys/vm/drop_caches   Slab内存管理机制 SLUB内存管理机制 http://w ...

  3. 垃圾回收GC:.Net自己主动内存管理 上(一)内存分配

    垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(二)内存算法 垃圾回收GC:.Net自己 ...

  4. Win3内存管理之私有内存跟共享内存的申请与释放

    Win3内存管理之私有内存跟共享内存的申请与释放 一丶内存简介私有内存申请 通过上一篇文章.我们理解了虚拟内存与物理内存的区别. 那么我们有API事专门申请虚拟内存与物理内存的. 有私有内存跟共享内存 ...

  5. JVM自动内存管理机制——Java内存区域(下)

    一.虚拟机参数配置 在上一篇<Java自动内存管理机制——Java内存区域(上)>中介绍了有关的基础知识,这一篇主要是通过一些示例来了解有关虚拟机参数的配置. 1.Java堆参数设置 a) ...

  6. 垃圾回收GC:.Net自己主动内存管理 上(二)内存算法

    垃圾回收GC:.Net自己主动内存管理 上(二)内存算法 垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(二)内存算法 垃圾回收GC:.Net自己 ...

  7. Linux-3.14.12内存管理笔记【构建内存管理框架(1)】

    传统的计算机结构中,整个物理内存都是一条线上的,CPU访问整个内存空间所需要的时间都是相同的.这种内存结构被称之为UMA(Uniform Memory Architecture,一致存储结构).但是随 ...

  8. Linux-3.14.12内存管理笔记【构建内存管理框架(2)】

    前面构建内存管理框架,已经将内存管理node节点设置完毕,接下来将是管理区和页面管理的构建.此处代码实现主要在于setup_arch()下的一处钩子:x86_init.paging.pagetable ...

  9. Linux-3.14.12内存管理笔记【构建内存管理框架(3)】

    此处接前文,分析free_area_init_nodes()函数最后部分,分析其末尾的循环: for_each_online_node(nid) { pg_data_t *pgdat = NODE_D ...

随机推荐

  1. TI的32位定点DSP库IQmath在H7和F4上的移植和使用

    说明: 1.最近在制作第2版DSP教程,除了ARM家的,这次重点了解下载TI的DSP库,特此移植了一个TI的IQmath. 2.初次使用这个定点库,感觉在各种Q格式的互转,Q格式数值和浮点数的互转处理 ...

  2. Css里的box-shadow的值分别代表什么

    以下为例: box-shadow:1px 2px 3px 4px color inset; 1px:表示沿x轴的正方向的长度(如果是负数,则为沿x轴的负方向的长度); 2px:表示沿y轴的正方向的长度 ...

  3. How to: Map a Persistent Class to a Database View Which Has No Key Field如何:映射持久化类到无主键数据库视图

    With XAF, you can build new applications from scratch or maintain existing databases. The How to: Ge ...

  4. ES6面向对象 动态添加标签页

    HTML <!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml&quo ...

  5. Android utils 之 日志工具类

    工具类 在开发的过程中,我们时常会对代码执行特定的处理,而这部分处理在代码中可能多次用到,为了代码的统一性.规范性等,通过建工具类的方式统一处理.接下来我会罗列各种工具类. 日志工具类 在utils文 ...

  6. centos重启出现type Control-D to continue【fsck使用】

    VMware vSphere克隆异常/dev/sda2:UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.(i.e.,without -a or -p optio ...

  7. 你真的理解Java 注解吗?

    你真的理解Java 注解吗? 1.什么是注解? 官方解释: Java 注解用于为 Java 代码提供元数据.作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的.Java ...

  8. steamdb cookie

    steamdb cookie import requests, re, os, pymysql, time from lxml import etree from steamdb.YDM import ...

  9. angularjs路由监听,uirouter感知路由变化,解决uirouter路由监听不生效的问题

     壹 ❀ 引 angularjs除了惊为天人的双向数据绑定外,路由也是出彩的一笔,通过路由配置,我们能在不发起页面跳转的情况下,对当前页内容进行整体更新,angularjs提供了ngRoute模块用于 ...

  10. mySql中Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggre的问题

    报错信息 Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'a.id' ...