Solarisの仮想ページから物理ページへのマッピングを見つける
-
25-10-2019 - |
質問
仮想ページのマッピングに物理的なプロセスの1つにアクセスしたいと思います。 OSはsolarisです。正確なバージョンはから尋ねることができます https://stackoverflow.com/users/760807/metallicpriest
次のようなリストを取得したい:
virt_addrs phys_addrs
0x000000-0x001000 0x537000-0x538000
0x001000-0x002000 0x832000-0x833000
...
CPUはx86またはx86_64です。ページサイズは4Kです。スワップがオフになります。私はページに興味がありません。それはFS(実行可能イメージ)に裏打ちされ、プロセスで使用されていません。
解決
PMAPとカーネルデバッガー(MDB -K)を使用してそれを実現できます。
PMAPは最初に(仮想)メモリ領域がプロセスで使用されるものを表示し、次にMDBでプロセス構造(PID2PROC)を取得し、P_ASフィールド(プロセスアドレススペース)を表示します。その値をパラメーターとして渡すと、VTOPコマンドはプロセス仮想から物理アドレスマッピングを表示できます。
例えば:
$ pmap -s 609
609: /usr/lib/utmpd
Address Bytes Pgsz Mode Mapped File
08046000 8K 4K rw--- [ stack ]
08050000 12K 4K r-x-- /usr/lib/utmpd
08063000 4K 4K rw--- /usr/lib/utmpd
...
# mdb -k
Loading modules: [ unix genunix specfs dtrace mac cpu.generic cpu_ms.AuthenticAMD.15 uppc pcplusmp scsi_vhci zfs ip hook neti arp usba sd sockfs stmf stmf_sbd s1394 fctl lofs random nfs sppp crypto cpc fcip ptm ufs logindmux ipc ]
> 0t609::pid2proc | ::print proc_t p_as
p_as = 0xffffff018cf38b00
> 08046000::vtop -a 0xffffff018cf38b00
virtual 8046000 mapped to physical a5c16000
> 8047000::vtop -a 0xffffff018cf38b00
virtual 8047000 mapped to physical a1267000
...
他のヒント
少し遅れていますが、ソラリスではまったく難しくありません。使用するだけです libkvm
.
これはSolaris 11のためです:
/* needed to get latest /proc structures */
#define _STRUCTURED_PROC 1
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <limits.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <kvm.h>
#include <sys/proc.h>
#include <sys/procfs.h>
void printVirtToPhysMappings( kvm_t *kvm, const char *pidStr );
int main( int argc, char **argv )
{
kvm_t *kvm = kvm_open( NULL, NULL, NULL, O_RDONLY, argv[ 0 ] );
for ( int ii = 1; ii < argc; ii++ )
{
printVirtToPhysMappings( kvm, argv[ ii ] );
}
kvm_close( kvm );
return( 0 );
}
void printVirtToPhysMappings( kvm_t *kvm, const char *pidStr )
{
char mapFile[ PATH_MAX ];
struct stat sb;
sprintf( mapFile, "/proc/%s/xmap", pidStr );
pid_t pid = strtol( pidStr, NULL, 0 );
struct proc *procPtr = kvm_getproc( kvm, pid );
int mapFD = open( mapFile, O_RDONLY );
fstat( mapFD, &sb );
size_t numMaps = sb.st_size / sizeof( prxmap_t );
prxmap_t mapEntries[ numMaps ];
pread( mapFD, mapEntries, sb.st_size, 0UL );
for ( size_t ii = 0; ii < numMaps; ii++ )
{
/* use the actual page size - page sizes can vary */
size_t pageSize = mapEntries[ ii ].pr_hatpagesize;
/* if page size is 0, page isn't mapped - set default
page size so we emit the output anyway */
if ( 0 == pageSize ) pageSize = 4096;
size_t numPages = mapEntries[ ii ].pr_size / pageSize;
for ( size_t jj = 0; jj < numPages; jj++ )
{
uintptr_t virtAddr = mapEntries[ ii ].pr_vaddr + jj * pageSize;
/* kvm_physaddr() is an undocumented feature of libkvm */
void *physAddr = ( void * ) kvm_physaddr( kvm, procPtr->p_as, virtAddr );
printf( "virtAddr: %p, page size: %ld, physAddr: %p\n", virtAddr, pageSize, physAddr );
}
}
close( mapFD );
}
それを実行するにはルートである必要があり、エラーチェックはまったくありません。悪いPIDを与えると、おそらくsegvになります。
所属していません StackOverflow