Linux 커널에서 페이지로 프로세스를 찾는 방법은 무엇입니까?

Linux 커널에서 페이지로 프로세스를 찾는 방법은 무엇입니까?

저는 Linux 커널 mm(메모리 관리)에 관한 프로젝트를 진행하고 있는데 페이지가 있는데 이 페이지가 속한 프로세스를 찾아야 합니다.

그러나 커널을 수정하지 않고서는 어떤 방법도 찾을 수 없습니다. 그래서 커널을 수정하지 않고도 이 작업을 수행할 수 있는지 알고 싶습니다.

좀 더 자세히 설명하자면, VMA가 있을 때 VMA를 해당 페이지로 변환하는 것도 가능한데, VMA나 페이지가 어느 프로세스에 속하는지 알고 싶습니다.

예를 들어 mm/page_io.c(Linux 커널 소스 트리)에서는 다음과 같습니다.

    int __swap_writepage(struct page *page, struct writeback_control *wbc,
        void (*end_write_func)(struct bio *, int))
{
        struct bio *bio;
        int ret, rw = WRITE;
        struct swap_info_struct *sis = page_swap_info(page);
...
        ret = bdev_write_page(sis->bdev, swap_page_sector(page), page, wbc);
        if (!ret) {
                count_vm_event(PSWPOUT);

                /* I should figure out what process is having the page above.
                 * But it is hard to know, because page is managed in LRU and
                 * it is not directly related to its process. What hints I have
                 * are page struct and some data structures which I could
                 * infer from the page only.
                 */

여러분의 멋진 답변을 기다리겠습니다. 감사합니다!

답변1

프로세스 메모리 페이지

@G-Man이 맞습니다. /proc파일 시스템이 정보를 제공할 수 있습니다. 그는 또한 정확하며 /proc/<pid>/maps몇 가지 정보를 제공할 것입니다. 예를 들어, 다음은 일부 /proc/<pid>/maps출력입니다.

7f2c09a0c000-7f2c09a0d000 r--p 00022000 08:03 3804420                    /usr/lib/ld-2.24.so
7f2c09a0d000-7f2c09a0e000 rw-p 00023000 08:03 3804420                    /usr/lib/ld-2.24.so
7f2c09a0e000-7f2c09a0f000 rw-p 00000000 00:00 0 
7ffc46cf9000-7ffc46d1a000 rw-p 00000000 00:00 0                          [stack]
7ffc46d86000-7ffc46d88000 r--p 00000000 00:00 0                          [vvar]
7ffc46d88000-7ffc46d8a000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

여기서 문제는 이 출력에서 ​​가상 페이지를 얻었지만 거기에서 실제 페이지와의 관계를 찾을 수 없다는 것입니다.

반면에 가상 메모리는 실제 메모리 페이지(스왑 영역 포함)에 매핑됩니다 /proc. 그것이 우리에게 무엇을 말하는지 /proc/<pid>/pagemap봅시다 :man 5 proc

/proc/[pid]/pagemap (since Linux 2.6.25)
       This  file  shows the mapping of each of the process's virtual pages into physical page frames or swap area.
       It contains one 64-bit value for each virtual page, with the bits set as follows:

            63     If set, the page is present in RAM.

            62     If set, the page is in swap space

            61 (since Linux 3.5)
                   The page is a file-mapped page or a shared anonymous page.

            60-56 (since Linux 3.11)
                   Zero

            55 (Since Linux 3.11)
                   PTE is soft-dirty (see the kernel source file Documentation/vm/soft-dirty.txt).

            54-0   If the page is present in RAM (bit 63), then these bits provide the page frame number, which can
                   be  used  to  index  /proc/kpageflags and /proc/kpagecount.  If the page is present in swap (bit
                   62), then bits 4-0 give the swap type, and bits 54-5 encode the swap offset.

좋습니다. 각 메모리 페이지에는 64비트 정수와 해당 페이지의 기능을 알려주는 여러 플래그가 있습니다. 읽으려면 /proc/<pid>/pagemap루트 액세스가 필요합니다. 또한 파일은 단지 64비트 정수 목록이므로 다음을 사용하겠습니다.

[~]# cat /proc/950/pagemap |xxd |less
...
000020c0: 0585 0600 0000 00a0 0285 0600 0000 00a0  ................
000020d0: 0385 0600 0000 00a0 6692 0600 0000 00a0  ........f.......
000020e0: 6792 0600 0000 00a0 488e 0600 0000 00a0  g.......H.......
000020f0: 498e 0600 0000 00a0 1c93 0600 0000 00a0  I...............
00002100: c45e 0600 0000 00a0 c55e 0600 0000 00a0  .^.......^......
00002110: c65e 0600 0000 00a0 c75e 0600 0000 00a0  .^.......^......
00002120: c85e 0600 0000 00a0 c95e 0600 0000 00a0  .^.......^......
00002130: ca5e 0600 0000 00a0 f05e 0600 0000 00a0  .^.......^......
00002140: f15e 0600 0000 00a0 f25e 0600 0000 00a0  .^.......^......
00002150: f35e 0600 0000 00a0 f45e 0600 0000 00a0  .^.......^......
00002160: f55e 0600 0000 00a0 f65e 0600 0000 00a0  .^.......^......
...
000035c0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000035d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000035e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000035f0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00003600: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00003610: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00003620: 0000 0000 0000 0000 c460 0400 0000 0081  .........`......
00003630: f02a 0400 0000 0081 b6f7 0100 0000 0081  .*..............
00003640: 804b 0300 0000 0081 0770 0400 0000 0081  .K.......p......
00003650: 2844 0500 0000 0081 3d9b 0400 0000 0081  (D......=.......
00003660: 192f 0400 0000 0081 813c 0300 0000 0081  ./.......<......
00003670: b1f7 0100 0000 0081 40a7 0300 0000 0081  ........@.......
00003680: ee58 0400 0000 0081 97c8 0300 0000 0081  .X..............
00003690: 9afa 0100 0000 0081 0000 0000 0000 0000  ................
000036a0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000036b0: 4d80 0400 0000 0081 0bb7 0400 0000 0081  M...............
000036c0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
...

위의 출력은 내 쉘 프로세스에서만 나온 것입니다. 프로세스의 전체 메모리에 대한 맵이기 때문에 많은 출력이 있습니다. 현재 매핑되지 않은 모든 부품에는 0만 포함됩니다.

c85e 0600 0000 00a0리틀 엔디안 시스템(xxd 출력의 0x2120)의 페이지를 예로 들어 a000 0000 0006 5ec8첫 번째 바이트가 0xa0이므로 비트 63이 설정되어 RAM의 페이지가 됩니다. 비트 번호는 0부터 시작하므로 비트 63이 마지막 비트입니다(비트 64 아님). 마지막 54비트는 실제 페이지의 인덱스인 0x65ec8(앞에 0이 많이 있음)입니다.

이제 페이지 2844 0500 0000 0081(xxd 출력의 0x3650)를 로 되돌릴 수 있습니다 8100 0000 0005 4428. 첫 번째 바이트는 비트 62가 설정된 0x81이므로 SWAP의 페이지입니다. 왜 비트 56이 설정되었는지 잘 모르겠습니다. 문서화되지 않은 내용이거나 사람 측의 오류(비트 55에 주목)일 수 있습니다. 그럼에도 불구하고 비트 54-0은 우리에게 다른 것을 알려줍니다. 0x28은 0x8인 스왑 유형을 제공합니다. 오프셋은 0x5442 >> 1(마지막 비트가 스왑 유형의 일부이므로) 0x2a21입니다.

(이번에는 부호/리틀 엔디안 계산을 엉망으로 만들지 않았으면 좋겠습니다. 제가 이 글을 처음 썼을 때 확실히 비트 수를 엉망으로 만들었습니다.)

페이지 처리 문제

위의 유일한 문제는 프로세스->페이지 매핑이라는 것입니다. 실제로는 페이지->프로세스가 아닙니다. 그러나 /proc/kpagecount현재 사용 중인 모든 페이지(페이지당 64비트 정수 하나의 또 다른 목록인 개수가 0보다 큰 모든 페이지)를 보려면 모든 항목을 검색할 수 있습니다. 그런 다음 모든 proc/<pid>디렉토리를 검색하십시오. 프로세스가 너무 빨리 시작되고 종료되어 찾을 수 없는 경우 /proc/<pid>에도 보안 정책이나 유사한 정책을 시행하려는 경우가 아니면 문제가 되지 않습니다. ( /proc상황이 너무 빨리 변하기 때문에 보안 정책을 절대 신뢰하지 마십시오).

추가의

이제 64비트 정수인 /proc/kpageflags0x54428 인덱스를 사용하여 페이지 플래그를 검색할 수 있습니다 . 0x54428th이에 대해서는 에도 설명되어 있습니다 man 5 proc.

관련 정보