GFP 플래그

밑줄 3개 ___GFP 플래그

직접 사용 금지 (밑줄 3개)

  • include/linux/gfp.h 내부에서만 사용되고 다른 소스에서는 직접 사용되지 않는다.
  • 커널 v4.4까지 새롭게 추가된 항목
    • ___GFP_ATOMIC
    • ___GFP_ACCOUNT
    • ___GFP_DIRECT_RECLAIM
    • ___GFP_KSWAPD_RECLAIM
  • 커널 v4.4까지 삭제된 항목
    • ___GFP_WAIT
    • ___GFP_NOACCOUNT
    • ___GFP_NOKSWAPD
/* Plain integer GFP bitmasks. Do not use this directly. */
#define ___GFP_DMA              0x01u
#define ___GFP_HIGHMEM          0x02u
#define ___GFP_DMA32            0x04u
#define ___GFP_MOVABLE          0x08u
#define ___GFP_WAIT             0x10u
#define ___GFP_HIGH             0x20u
#define ___GFP_IO               0x40u
#define ___GFP_FS               0x80u
#define ___GFP_COLD             0x100u
#define ___GFP_NOWARN           0x200u
#define ___GFP_REPEAT           0x400u
#define ___GFP_NOFAIL           0x800u
#define ___GFP_NORETRY          0x1000u
#define ___GFP_MEMALLOC         0x2000u
#define ___GFP_COMP             0x4000u
#define ___GFP_ZERO             0x8000u
#define ___GFP_NOMEMALLOC       0x10000u
#define ___GFP_HARDWALL         0x20000u
#define ___GFP_THISNODE         0x40000u
#define ___GFP_RECLAIMABLE      0x80000u
#define ___GFP_NOACCOUNT        0x100000u
#define ___GFP_NOTRACK          0x200000u
#define ___GFP_NO_KSWAPD        0x400000u
#define ___GFP_OTHER_NODE       0x800000u
#define ___GFP_WRITE            0x1000000u
  • ___GFP_DMA
    • ZONE_DMA 영역에 할당 요청한다.
  • ___GFP_HIGHMEM
    • ZONE_HIGHMEM 영역에 할당 요청한다.
  • ___GFP_DMA32
    • ZONE_DMA32 영역에 할당 요청한다.
  • ___GFP_MOVABLE
    • 두 가지 용도로 사용
      • ZONE_MOVABLE이 가용할 때 이 영역에 할당 요청한다.
      • 페이지 이주가 가능하도록 할당 요청한다.
  • ___GFP_RECLAIMABLE
    • 회수 가능한 페이지로 할당 요청한다.
  • ___GFP_WAIT
    • 메모리 할당을 하는 동안 sleep을 허용하도록 요청한다.
  • ___GFP_HIGH
    • 높은 우선 순위에서 처리되도록 요청한다.
  • ___GFP_IO
    • 메모리 할당을 하는 동안 어떠한 I/O 처리도 가능하도록 요청한다.
  • ___GFP_FS
    • 메모리 할당을 하는 동안 File System calls 가능하도록 요청한다.
  • ___GFP_COLD
    • 메모리 파편화에 영향을 덜 주도록 warm(hot) 페이지 대신 cold 페이지에서 관리하도록 요청한다
  • ___GFP_NOWARN
    • 메모리 할당이 실패할 때 어떠한 경고도 처리하지 않도록 요청한다.
  • ___GFP_REPEAT
    • 메모리 할당이 처음 실패하는 경우 한 번 더 시도하도록 요청한다.
  • ___GFP_NOFAIL
    • 실패를 허용하지 않고, 메모리 할당 요청에 대해 성공할 때까지 처리하도록 요청한다.
  • ___GFP_NORETRY
    • 메모리 할당 요청에 대해 실패 시 재시도 하지 않도록 요청한다.
  • ___GFP_MEMALLOC
    • 메모리 할당에 비상 영역을 사용할 수 있도록 요청한다.
  • ___GFP_COMP
    • 메타 데이터 또는 연속된 복합 페이지를 구성하도록 요청한다.
  • ___GFP_ZERO
    • 할당된 영역을 0으로 초기화 하도록 요청한다.
  • ___GFP_NOMEMALLOC
    • 메모리 할당에 비상 영역을 사용하지 않도록 요청한다.
  • ___GFP_HARDWALL
    • 현재 태스크에 지정된 cpuset 메모리 할당 정책을 사용하게 요청한다.
  • ___GFP_THISNODE
    • 지정된 노드에서만 할당을 허용한다.
  • ___GFP_NOACCOUNT
    • kmemcg(메모리 Control Group)의 사용량 통제를 받지 않도록 요청한다.
  • ___GFP_NOTRACK
    • kmemcheck를 사용한 디버그 트래킹을 허용하지 않도록 요청한다.
  •  ___GFP_NO_KSWAPD
    • 할당된 페이지가 Swap 파일로 이동할 수 없게 요청한다.
  • ___GFP_OTHERNODE
    • 리모트 노드에서 할당을 하도록 요청한다.
  • ___GFP_WRITE
    • dirty(쓰기용 파일 캐시)  페이지 할당을 요청한다.

 

밑줄 2개 __GFP 플래그

ZONE 관련 (밑줄 2개)

  • 하위 4개의 비트를 사용한다.
/*
 * Physical address zone modifiers (see linux/mmzone.h - low four bits)
 *
 * Do not put any conditional on these. If necessary modify the definitions
 * without the underscores and use them consistently. The definitions here may
 * be used in bit comparisons.
 */
#define __GFP_DMA       ((__force gfp_t)___GFP_DMA)
#define __GFP_HIGHMEM   ((__force gfp_t)___GFP_HIGHMEM)
#define __GFP_DMA32     ((__force gfp_t)___GFP_DMA32)
#define __GFP_MOVABLE   ((__force gfp_t)___GFP_MOVABLE)  /* Page is movable */
#define GFP_ZONEMASK    (__GFP_DMA|__GFP_HIGHMEM|__GFP_DMA32|__GFP_MOVABLE)
  • __GFP_DMA
    • ZONE_DMA 영역에 할당 요청
  • __GFP_HIGHMEM
    • ZONE_HIGHMEM 영역에 할당 요청
  • __GFP_DMA32
    • ZONE_DMA32 영역에 할당 요청
  • __GFP_MOVABLE
    • ZONE_MOVABLE이 허락되는 경우 이 영역에 할당 요청
  • GFP_ZONEMASK
    • 위의 4개 zone을 포함
    • GFP 플래그를 사용하지 하지 않을 때 일반적으로 ZONE_NORMAL을 의미한다.

 

Page Mobility 와 장소 hint 관련 (밑줄 2개)

/*
 * Page mobility and placement hints
 *
 * These flags provide hints about how mobile the page is. Pages with similar
 * mobility are placed within the same pageblocks to minimise problems due
 * to external fragmentation.
 *
 * __GFP_MOVABLE (also a zone modifier) indicates that the page can be
 *   moved by page migration during memory compaction or can be reclaimed.
 *
 * __GFP_RECLAIMABLE is used for slab allocations that specify
 *   SLAB_RECLAIM_ACCOUNT and whose pages can be freed via shrinkers.
 *
 * __GFP_WRITE indicates the caller intends to dirty the page. Where possible,
 *   these pages will be spread between local zones to avoid all the dirty
 *   pages being in one zone (fair zone allocation policy).
 *
 * __GFP_HARDWALL enforces the cpuset memory allocation policy.
 *
 * __GFP_THISNODE forces the allocation to be satisified from the requested
 *   node with no fallbacks or placement policy enforcements.
 *
 * __GFP_ACCOUNT causes the allocation to be accounted to kmemcg (only relevant
 *   to kmem allocations).
 */
#define __GFP_RECLAIMABLE ((__force gfp_t)___GFP_RECLAIMABLE)
#define __GFP_WRITE     ((__force gfp_t)___GFP_WRITE)
#define __GFP_HARDWALL   ((__force gfp_t)___GFP_HARDWALL)
#define __GFP_THISNODE  ((__force gfp_t)___GFP_THISNODE)
#define __GFP_ACCOUNT   ((__force gfp_t)___GFP_ACCOUNT)
  • __GFP_RECLAIMABLE
    • 회수 가능한 페이지로 할당한다.
  • __GFP_WRITE
    • dirty(쓰기용 파일 캐시)  페이지 할당을 요청한다.
  • __GFP_HARDWALL
    • 현재 태스크에 지정된 cpuset 메모리 할당 정책을 사용하게 요청한다.
  • __GFP_THISNODE
    • 지정된 노드에서만 할당을 허용한다.
  • __GFP_ACCOUNT
    • kmemcg(메모리 Control Group)의 사용량 통제를 받지 않도록 요청한다.

 

워터마크 관련 (밑줄 2개)

/*
 * Watermark modifiers -- controls access to emergency reserves
 *
 * __GFP_HIGH indicates that the caller is high-priority and that granting
 *   the request is necessary before the system can make forward progress.
 *   For example, creating an IO context to clean pages.
 *
 * __GFP_ATOMIC indicates that the caller cannot reclaim or sleep and is
 *   high priority. Users are typically interrupt handlers. This may be
 *   used in conjunction with __GFP_HIGH
 *
 * __GFP_MEMALLOC allows access to all memory. This should only be used when
 *   the caller guarantees the allocation will allow more memory to be freed
 *   very shortly e.g. process exiting or swapping. Users either should
 *   be the MM or co-ordinating closely with the VM (e.g. swap over NFS).
 *
 * __GFP_NOMEMALLOC is used to explicitly forbid access to emergency reserves.
 *   This takes precedence over the __GFP_MEMALLOC flag if both are set.
 */
#define __GFP_ATOMIC    ((__force gfp_t)___GFP_ATOMIC)
#define __GFP_HIGH      ((__force gfp_t)___GFP_HIGH)
#define __GFP_MEMALLOC  ((__force gfp_t)___GFP_MEMALLOC)
#define __GFP_NOMEMALLOC ((__force gfp_t)___GFP_NOMEMALLOC)
  • __GFP_ATOMIC
    • 페이지 회수나 슬립이 허용되지 않고 높은 우선 순위로 처리되도록 요청한다.
    • 인터럽트 핸들러들에서 보통 사용되며 __GFP_HIGH와 붙여서 사용될 수도 있다.
  • __GFP_HIGH
    • 높은 우선 순위로 처리되도록 요청한다. \
  • __GFP_MEMALLOC
    • 모든 메모리로의 접근을 허가하도록 요청한다.
    • 프로세스 종료나 스와핑의 사용 예와 같이 매우 짧은 시간내 메모리 할당이 요구될 때 필요하다.
  • __GFP_NOMEMALLOC
    • 비상용 reserves 영역을 이용하지 못하게 엄격히 금지하도록 요청한다.

 

페이지 회수관련 (밑줄 2개)

/*
 * Reclaim modifiers
 *
 * __GFP_IO can start physical IO.
 *
 * __GFP_FS can call down to the low-level FS. Clearing the flag avoids the
 *   allocator recursing into the filesystem which might already be holding
 *   locks.
 *
 * __GFP_DIRECT_RECLAIM indicates that the caller may enter direct reclaim.
 *   This flag can be cleared to avoid unnecessary delays when a fallback
 *   option is available.
 *
 * __GFP_KSWAPD_RECLAIM indicates that the caller wants to wake kswapd when
 *   the low watermark is reached and have it reclaim pages until the high
 *   watermark is reached. A caller may wish to clear this flag when fallback
 *   options are available and the reclaim is likely to disrupt the system. The
 *   canonical example is THP allocation where a fallback is cheap but
 *   reclaim/compaction may cause indirect stalls.
 *
 * __GFP_RECLAIM is shorthand to allow/forbid both direct and kswapd reclaim.
 *
 * __GFP_REPEAT: Try hard to allocate the memory, but the allocation attempt
 *   _might_ fail.  This depends upon the particular VM implementation.
 *
 * __GFP_NOFAIL: The VM implementation _must_ retry infinitely: the caller
 *   cannot handle allocation failures. New users should be evaluated carefully
 *   (and the flag should be used only when there is no reasonable failure
 *   policy) but it is definitely preferable to use the flag rather than
 *   opencode endless loop around allocator.
 *
 * __GFP_NORETRY: The VM implementation must not retry indefinitely and will
 *   return NULL when direct reclaim and memory compaction have failed to allow
 *   the allocation to succeed.  The OOM killer is not called with the current
 *   implementation.
 */
#define __GFP_IO        ((__force gfp_t)___GFP_IO)
#define __GFP_FS        ((__force gfp_t)___GFP_FS)
#define __GFP_DIRECT_RECLAIM    ((__force gfp_t)___GFP_DIRECT_RECLAIM) /* Caller can reclaim */
#define __GFP_KSWAPD_RECLAIM    ((__force gfp_t)___GFP_KSWAPD_RECLAIM) /* kswapd can wake */
#define __GFP_RECLAIM ((__force gfp_t)(___GFP_DIRECT_RECLAIM|___GFP_KSWAPD_RECLAIM))
#define __GFP_REPEAT    ((__force gfp_t)___GFP_REPEAT)
#define __GFP_NOFAIL    ((__force gfp_t)___GFP_NOFAIL)
#define __GFP_NORETRY   ((__force gfp_t)___GFP_NORETRY)
  • __GFP_IO
    • 메모리 할당을 하는 동안 어떠한 I/O 처리도 가능하도록 요청한다.
  • __GFP_FS
    • 메모리 할당을 하는 동안 File System calls 가능하도록 요청한다.
  • __GFP_DIRECT_RECLAIM
    • 페이지 할당 요청 시 free 페이지가 부족한 경우 direct reclaim(호출자가 직접 회수)을 들어갈 수 있도록 요청한다.
    • 메모리 할당 관련하여 준비된 fallback이 있는 경우 fallback 루틴에서는 불필요한 지연을 없애기 위해 명확히 이 플래그를 제거하여 요청한다.
  • __GFP_KSWAPD_RECLAIM
    • low 워터마크에 접근하는 경우 kswapd를 깨워서 high 워터마크에 오를때까지 페이지를 회수하도록 요청한다.
  • __GFP_RECLAIM
    • 위 2가지 플래그 즉, direct reclaim과 kswapd를 사용한 회수를 동시에 요청한다.
  • __GFP_REPEAT
    • 메모리 할당이 처음 실패하는 경우 한 번 더 시도하도록 요청한다.
  • __GFP_NOFAIL
    • 실패를 허용하지 않고, 메모리 할당 요청에 대해 성공할 때까지 처리하도록 요청한다.
  • __GFP_NORETRY
    • 메모리 할당 요청에 대해 실패 시 재시도 하지 않도록 요청한다.

 

Action 관련 (밑줄 2개)

/*
 * Action modifiers
 *
 * __GFP_COLD indicates that the caller does not expect to be used in the near
 *   future. Where possible, a cache-cold page will be returned.
 *
 * __GFP_NOWARN suppresses allocation failure reports.
 *
 * __GFP_COMP address compound page metadata.
 *
 * __GFP_ZERO returns a zeroed page on success.
 *
 * __GFP_NOTRACK avoids tracking with kmemcheck.
 *
 * __GFP_NOTRACK_FALSE_POSITIVE is an alias of __GFP_NOTRACK. It's a means of
 *   distinguishing in the source between false positives and allocations that
 *   cannot be supported (e.g. page tables).
 *
 * __GFP_OTHER_NODE is for allocations that are on a remote node but that
 *   should not be accounted for as a remote allocation in vmstat. A
 *   typical user would be khugepaged collapsing a huge page on a remote
 *   node.
 */
#define __GFP_COLD      ((__force gfp_t)___GFP_COLD)
#define __GFP_NOWARN    ((__force gfp_t)___GFP_NOWARN)
#define __GFP_COMP      ((__force gfp_t)___GFP_COMP)
#define __GFP_ZERO      ((__force gfp_t)___GFP_ZERO)
#define __GFP_NOTRACK   ((__force gfp_t)___GFP_NOTRACK)
#define __GFP_NOTRACK_FALSE_POSITIVE (__GFP_NOTRACK)
#define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE)
  • __GFP_COLD
    • 메모리 파편화에 영향을 덜 주도록 warm(hot) 페이지 대신 cold 페이지에서 관리하도록 요청한다
  • __GFP_NOWARN
    • 메모리 할당이 실패할 때 어떠한 경고도 처리하지 않도록 요청한다.
  • __GFP_COMP
    • 메타 데이터 또는 연속된 복합 페이지를 구성하도록 요청한다.
  • __GFP_ZERO
    • 할당된 영역을 0으로 초기화 하도록 요청한다.
  • __GFP_NOTRACK
    • kmemcheck를 사용한 디버그 트래킹을 허용하지 않도록 요청한다.
  • __GFP_NOTRACK_FALSE_POSITIVE
    • kmemcheck를 사용한 false positive(가짜 긍정) 디버그 트래킹을 허용하지 않도록 요청한다.
  • __GFP_OTHERNODE
    • 리모트 노드에서 할당을 하도록 요청한다.

 

밑줄 없는 GFP 플래그

/*
 * Useful GFP flag combinations that are commonly used. It is recommended
 * that subsystems start with one of these combinations and then set/clear
 * __GFP_FOO flags as necessary.
 *
 * GFP_ATOMIC users can not sleep and need the allocation to succeed. A lower
 *   watermark is applied to allow access to "atomic reserves"
 *
 * GFP_KERNEL is typical for kernel-internal allocations. The caller requires
 *   ZONE_NORMAL or a lower zone for direct access but can direct reclaim.
 *
 * GFP_KERNEL_ACCOUNT is the same as GFP_KERNEL, except the allocation is
 *   accounted to kmemcg.
 *
 * GFP_NOWAIT is for kernel allocations that should not stall for direct
 *   reclaim, start physical IO or use any filesystem callback.
 *
 * GFP_NOIO will use direct reclaim to discard clean pages or slab pages
 *   that do not require the starting of any physical IO.
 *
 * GFP_NOFS will use direct reclaim but will not use any filesystem interfaces.
 *
 * GFP_USER is for userspace allocations that also need to be directly
 *   accessibly by the kernel or hardware. It is typically used by hardware
 *   for buffers that are mapped to userspace (e.g. graphics) that hardware
 *   still must DMA to. cpuset limits are enforced for these allocations.
 *
 * GFP_DMA exists for historical reasons and should be avoided where possible.
 *   The flags indicates that the caller requires that the lowest zone be
 *   used (ZONE_DMA or 16M on x86-64). Ideally, this would be removed but
 *   it would require careful auditing as some users really require it and
 *   others use the flag to avoid lowmem reserves in ZONE_DMA and treat the
 *   lowest zone as a type of emergency reserve.
 *
 * GFP_DMA32 is similar to GFP_DMA except that the caller requires a 32-bit
 *   address.
 *
 * GFP_DMA32 is similar to GFP_DMA except that the caller requires a 32-bit
 *   address.
 *
 * GFP_HIGHUSER is for userspace allocations that may be mapped to userspace,
 *   do not need to be directly accessible by the kernel but that cannot
 *   move once in use. An example may be a hardware allocation that maps
 *   data directly into userspace but has no addressing limitations.
 *
 * GFP_HIGHUSER_MOVABLE is for userspace allocations that the kernel does not
 *   need direct access to but can use kmap() when access is required. They
 *   are expected to be movable via page reclaim or page migration. Typically,
 *   pages on the LRU would also be allocated with GFP_HIGHUSER_MOVABLE.
 *
 * GFP_TRANSHUGE is used for THP allocations. They are compound allocations
 *   that will fail quickly if memory is not available and will not wake
 *   kswapd on failure.
 */
#define GFP_ATOMIC      (__GFP_HIGH|__GFP_ATOMIC|__GFP_KSWAPD_RECLAIM)
#define GFP_KERNEL      (__GFP_RECLAIM | __GFP_IO | __GFP_FS)
#define GFP_KERNEL_ACCOUNT (GFP_KERNEL | __GFP_ACCOUNT)
#define GFP_NOWAIT      (__GFP_KSWAPD_RECLAIM)
#define GFP_NOIO        (__GFP_RECLAIM)
#define GFP_NOFS        (__GFP_RECLAIM | __GFP_IO)
#define GFP_TEMPORARY   (__GFP_RECLAIM | __GFP_IO | __GFP_FS | \
                         __GFP_RECLAIMABLE)
#define GFP_USER        (__GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_HARDWALL)
#define GFP_DMA         __GFP_DMA
#define GFP_DMA32       __GFP_DMA32
#define GFP_HIGHUSER    (GFP_USER | __GFP_HIGHMEM)
#define GFP_HIGHUSER_MOVABLE    (GFP_HIGHUSER | __GFP_MOVABLE)
#define GFP_TRANSHUGE   ((GFP_HIGHUSER_MOVABLE | __GFP_COMP | \
                         __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN) & \
                         ~__GFP_RECLAIM)
  • GFP_ATOMIC
    • 슬립되지 않아야 하고 “atomic reserves”으로의 접근이 허락된  low 워터마크가 적용되게 요청한다.
  • GFP_KERNEL
    • 커널 내부 알고리즘이 이용하는 할당을 위해 사용되며, direct-reclaim이나 kswapd를 통한 reclaim이 가능하고 io 및 fs의 이용이 가능한 상태로 ZONE_NORMAL 또는 lower zone을 사용하도록 요청한다.
  • GFP_KERNEL_ACCOUNT
    • kmemcg(메모리 Control Group)의 사용량 통제를 받는것을 제외하고 GFP_KERNEL과 동일하다.
  • GFP_NOWAIT
    • 커널 할당을 위해 kswapd를 사용한 reclaim이 가능하도록 요청한다.
  • GFP_NOIO
    • direct reclaim을 이용 시 클린 페이지 또는 slab 페이지들을 버릴 수 없도록 한다.
  • GFP_NOFS
    • direct reclaim을 이용 시 io 처리는 가능하나 file system 인터페이스를 이용하지 못한다.
  • GFP_USER
    • userspace 할당을 위해 커널 및 하드웨어에 의해 직접 접근이 가능하도록 요청한다.
    • 현재 태스크에 지정된 cpuset 메모리 할당 정책을 사용하게 요청한다.
  • GFP_DMA
    • 가장 낮은 zone(ZONE_DMA)을 요청한다.
  • GFP_DMA32
    • ZONE_DMA를 요청한다.
  • GFP_HIGHUSER
    • userspace 할당을 위해 GFP_USER에 highmem 사용을 요청한다.
  • GFP_HIGHUSER_MOVABLE
    • userspace 할당을 위해 GFP_USER에 highmem 및 movable migrate 타입 사용을 요청한다.
  • GFP_TRANSHUGE
    • THP(Transparent Huge Page) 할당을 위해 사용되며 메모리 부족시 빠르게 실패하게 한다.
    • 실패한 경우에도 kswapd를 깨우지 않게 한다.

4 thoughts to “GFP 플래그”

  1. __GFP_DIRECT_RECLAIM에 대해서 궁금한점이 있습니다.
    ‘fallback이 유효한 경우 불필요한 지연을 없애기 위해 명확히 지정한다.’ 라고 설명하셨는데, 주석에서 말한 clear는 제거될 수 있다는 뜻으로 보입니다. 실제로 block/bio.c의 bvec_alloc() 코드 내부에 보면

    206 if (*idx == BVEC_POOL_MAX) {
    207 fallback:
    208 bvl = mempool_alloc(pool, gfp_mask);
    209 } else {
    210 struct biovec_slab *bvs = bvec_slabs + *idx;
    211 gfp_t __gfp_mask = gfp_mask & ~(__GFP_DIRECT_RECLAIM | __GFP_IO);
    212
    213 /*
    214 * Make this allocation restricted and don’t dump info on
    215 * allocation failures, since we’ll fallback to the mempool
    216 * in case of failure.
    217 */
    218 __gfp_mask |= __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN;
    219
    220 /*
    221 * Try a slab allocation. If this fails and __GFP_DIRECT_RECLAIM
    222 * is set, retry with the 1-entry mempool
    223 */
    224 bvl = kmem_cache_alloc(bvs->slab, __gfp_mask);

    이런 부분이 있습니다. fallback으로 사용할 mempool이 있는 경우에는 __GFP_DIRECT_RECLAIM flag를 제거하겠다는 뜻으로 이해하였습니다.
    제가 잘못 이해한 것인지, 의견 주시면 감사하겠습니다!

    1. 안녕하세요?

      __GFP_DIRECT_RECLAIM 관련하여 제 글의 해석이 반대로 설명된 부분이 있어 수정하였습니다.

      할당 관련하여 사용자의 fallback 코드가 준비된 경우 그 fallback 코드에서는
      명확히 __GFP_DIRECT_RECLAIM 플래그를 지우고 사용하여 지연 시간을 줄일 수 있습니다.

      잘 이해하고 질문하셨겠지만, 혹시나 조금 더 설명드리면,
      첫 번째 메모리 할당 시 direct-reclaim 옵션을 가지고도 실패하면, 두 번째 메모리 할당 시에는 direct-reclaim을 곧바로 또 해봤자, 메모리 회수가 될 확률이 거의 없습니다. 그냥 시간만 버리는 것입니다.

      따라서 메모리 할당에 대한 fallback 코드가 준비된 경우에는 direct-reclaim 플래그를 제거하고 진행하는 것이 좋습니다.

      감사합니다.

      1. 모기향 책의 저자이시다니! 이제야 보석같은 사이트를 보고 이것저것 공부하고 있습니다. 감사합니다.

        GFP_DIRECT_RECLAIM에 대해 좀 오해가 있으신 것 같아서 정정해 드리자면,. 특별히 단시간에 메모리 할당이 매우 많은 경우가 아니라면, 이게 있다고 지연이 추가로 생기거나 그러지는 않습니다. 다만, 이 플래그를 주면 안되는 경우가 있습니다.
        – 잠들면 안되는 경우. 메모리 할당하다 잠드는 이유는 direct reclaim이 동작하기 때문입니다. GFP_ATOMIC이 그 용도이긴 한데, ATOMIC에게는 min wmark를 조금 더 허용한다던가 하는 추가 보상이 좀 있고, 그런것도 필요 없다면 DIRECT_RECLAIM만 지우면 됩니다. (그런데, 그럴 거면 걍 ATOMIC을 쓰면 됩니다..)

        GFP_DIRECT_RECLAIM이 포함된 GFP_KERNEL 같은 걸 주고 메모리 할당이 실패했다면.. 그건 사실 시스템의 메모리 운용에 심각한 문제가 있거나 필요한 워킹셋에 비해 시스템 메모리가 적다는 뜻이라서 좀 살펴봐야 합니다.
        이 플래그를 지우고 할당하는 경우가 있다면, 위에서 말씀하셨듯이, 빠르게 fallback으로 넘어가려는 경우입니다. 여러 가지 이유가 있을텐데, 비상금이 있는 경우, 용돈 생기길 기다리기 보다 비상금 먼저 꺼내 쓰는 경우이기도 하고, compound page를 받아 쪼개 쓰고 싶은데, 마냥 기다리긴 싫고, 안되면 작은 페이지들을 받는 경우에 해당하기도 합니다.

        1. 안녕하세요?

          정확히 설명하셨습니다.

          조금 더 보강하자면 __GFP_DIRECT_RECLAIM 같은 플래그는 사용자들이 일반적인 상황 시에 사용하는 플래그가 아닙니다.
          사용자들은 일반적으로 GFP_KERNEL을 사용하거나 interrupt context 내에서 메모리 할당을 원할때에만 GFP_ATOMIC 플래그를 이용합니다.

          커널 내부에서 두 줄짜리 __GFP_DIRECT_RECLAIM을 사용할 때와 사용하지 않을 때의 차이는 다음과 같습니다.
          – 위 플래그 없이 메모리 부족한 상황이 발생했을 때 그냥 에러를 반환한다.
          – 위 플래그를 가지고 메모리 부족한 상황이 발생했을 때 direct-reclaim을 시도하여서라도 메모리를 확보하는 노력을 한다.

          GFP_KERNEL을 사용하여 커널 내부의 코드를 진행해보면 메모리 부족 시 할당이 실패하면 약간의 변화를 주어 반복하는데, 특정 시도 시에는 __GFP_DIRECT_RECLAIM 플래그를 빼고 시도를 하는 케이스를 볼 수 있습니다. 이는 이미 플래그를 붙여서 시도 했는데도 실패하였었고, 약간의 상황을 바꾸어 다시 시도할 때 reclaim으로 인한 시간 낭비를 줄이기 위해 __GFP_DIRECT_RECLAIM 플래그를 빼고 시행해야 다시 불필요한 회수 동작에 들어가지 않습니다. 이러한 이유로 사용자가 GFP_KERNEL을 사용하여 페이지 할당을 시도하더라도 커널 내부에서 일부 상황 시에 위의 플래그를 빼는 것으로 중복 reclaim에 의한 지연시간을 줄이는 목적으로도 사용하고 있습니다.

          감사합니다.

댓글 남기기