NAME

move_pages - 프로세스의 개별 페이지들을 다른 노드로 옮기기

SYNOPSIS

#include <numaif.h>

long move_pages(int pid, unsigned long count, void **pages,
                const int *nodes, int *status, int flags);

-lnuma로 링크.

주의: 이 시스템 호출에 대한 glibc 래퍼가 없다. NOTES 참고.

DESCRIPTION

move_pages()는 프로세스 pid의 지정한 pagesnodes로 지정한 메모리 노드들로 옮긴다. 이동 결과가 status에 반영된다. flags는 이동할 페이지들에 대한 제약을 나타낸다.

pid는 이동할 페이지들이 있는 프로세스의 ID이다. pid가 0이면 move_pages()는 호출 프로세스의 페이지를 옮긴다.

다른 프로세스의 페이지를 옮기려면 다음 특권이 필요하다.

count는 옮길 페이지 개수이다. 세 배열 pages, nodes, status의 크기를 규정한다.

pages는 옮겨야 할 페이지들에 대한 포인터들의 배열이다. 이 포인터들은 페이지 경계에 맞춰 정렬돼 있어야 한다. pid로 지정한 프로세스에게 보이는 주소로 지정한다.

nodes는 각 페이지에 대해 원하는 위치를 지정한 정수들의 배열이다. 배열의 각 항목은 노드 번호이다. nodes가 NULL일 수도 있는데, 그 경우 move_pages()는 페이지를 옮기지 않고 대신 각 페이지가 현재 자리한 노드를 status 배열로 반환한다. 옮겨야 할 페이지들을 알아내기 위해 각 페이지의 상태를 얻어야 할 수 있다.

status는 정수들의 배열이며 각 페이지의 상태를 반환한다. move_pages()가 오류를 반환하지 않은 경우에만 배열이 유효한 값들을 담고 있다. 배열의 값을 실제 numa 노드를 나타낼 수 없는 값이나 유효한 상태 배열 오류 값으로 미리 초기화해 두면 이동한 페이지들을 알아내는 데 도움이 될 수 있다.

flags는 옮길 페이지의 종류를 지정한다. MPOL_MF_MOVE는 프로세스에서 배타적으로 사용 중인 페이지들만 옮기라는 뜻이다. MPOL_MF_MOVE_ALL은 여러 프로세스들끼리 공유하는 페이지들도 옮길 수 있다는 뜻이다. MPOL_MF_MOVE_ALL을 쓰려면 프로세스가 특권(CAP_SYS_NICE)을 가지고 있어야 한다.

status 배열의 페이지 상태

status 배열의 각 항목으로 다음 값들을 반환할 수 있다.

0..MAX_NUMNODES
페이지가 자리한 노드를 나타낸다.
-EACCES
페이지를 여러 프로세스가 맵 하고 있어서 MPOL_MF_MOVE_ALL을 지정해야만 옮길 수 있다.
-EBUSY
페이지가 현재 사용 중이어서 옮길 수 없다. 나중에 다시 시도하라. 페이지로 I/O를 하는 중이거나 다른 커널 서브시스템에서 페이지에 대한 참조를 잡고 있는 경우이다.
-EFAULT
제로 페이지이거나 프로세스가 맵 하지 않은 메모리 영역이다.
-EIO
페이지를 내려 쓸 수 없다. 페이지가 변경됐는데 변경된 페이지를 옮길 수 있게 해 주는 이전 함수를 파일 시스템에서 제공하지 않기 때문에 페이지를 옮기기 위해선 아래로 기록해야 한다.
-EINVAL
변경된 페이지를 이동할 수 없다. 파일 시스템에서 이전 함수를 제공하지 않으며 페이지를 내려 쓸 수 없다.
-ENOENT
페이지가 존재하지 않는다.
-ENOMEM
대상 노드에서 메모리를 할당할 수 없다.

RETURN VALUE

성공 시 move_pages()는 0을 반환한다. 오류 시 -1을 반환하며 오류를 나타내도록 errno를 설정한다. 양수 값을 반환하는 경우 그 값은 이동 안 된 페이지 개수이다.

ERRORS

양수 값
중대하지 않은 원인으로 인한 것인 경우 이동 안 된 페이지들의 개수.
E2BIG
옮길 페이지가 너무 많다. 리눅스 2.6.29부터는 커널에서 이 오류를 내놓지 않는다.
EACCES
한 대상 노드를 현재 cpuset에서 허용하지 않는다.
EFAULT
매개변수 배열에 접근할 수 없다.
EINVAL
MPOL_MF_MOVEMPOL_MF_MOVE_ALL 외의 플래그를 지정했거나 커널 스레드의 페이지를 이동하려는 시도가 이뤄졌다.
ENODEV
한 대상 노드가 온라인이 아니다.
EPERM
호출자가 충분한 특권(CAP_SYS_NICE) 없이 MPOL_MF_MOVE_ALL을 지정했다. 또는 호출자가 다른 사용자에게 속한 프로세스의 페이지를 옮기려고 시도했는데 그렇게 하기 위한 특권(CAP_SYS_NICE)을 가지고 있지 않았다.
ESRCH
프로세스가 존재하지 않는다.

VERSIONS

리눅스 버전 2.6.18에서 move_pages()가 처음 등장했다.

CONFORMING TO

이 시스템 호출은 리눅스 전용이다.

NOTES

glibc에서 이 시스템 호출의 래퍼를 제공하지 않는다. 라이브러리 지원에 대한 정보는 numa(7)를 보라.

get_mempolicy(2)MPOL_F_MEMS_ALLOWED 플래그로 사용하면 현재 cpuset에서 허용하는 노드들의 집합을 얻을 수 있다. 참고로 그 정보는 수동 내지 자동으로 이뤄지는 cpuset 재구성으로 인해 언제든 바뀔 수 있다.

이 함수를 사용하면 페이지들의 위치(노드)가 지정 주소(mbind(2)) 및/또는 지정 프로세스(set_mempolicy(2))에 대해 설정한 메모리 정책과 어긋나게 될 수도 있다. 다시 말해 메모리 정책이 move_pages()에서 쓰는 목적지 노드를 제약하지 않는다.

<numaif.h> 헤더는 glibc에 포함되어 있지 않으며 libnuma-devel 내지 그와 비슷한 패키지를 설치해야 한다.

SEE ALSO

get_mempolicy(2), mbind(2), set_mempolicy(2), numa(3), numa_maps(5), cpuset(7), numa(7), migratepages(8), numastat(8)


2021-03-22