私の/proc/meminfo
プログラムには約500MBが割り当てられていますShmem
。より具体的な数字を知りたいです。ここで説明を見つけました。
https://lists.kernelnewbies.org/pipermail/kernelnewbies/2013-July/008628.html
これには、tmpfsメモリ、SysV共有メモリ(ipc / shm.cから)、POSIX共有メモリ(/ dev / shm [tmpfs]の下)、共有匿名マップ(/ dev / zeroのmmapとMAP_SHARED:参照)が含まれます。 drivers/char/mem.c から shmem_zero_setup() 呼び出し: mm/shmem.c を介したページ割り当て。
2->開発者のコメントによると、NR_SHMEMにはtmpfsとGEMページが含まれています。 GEMページとは何ですか?
はい、グラフィカル実行マネージャはshmemを使用してGPUと共有されるオブジェクトを保存します。 drivers/gpu/drm/ で shmem_read_mapping_page*() を使用するをご覧ください。
私は薬です
- 経由でユーザーに表示されるtmpfsには50MBがあります
df -h -t tmpfs
。 - sysvipc共有メモリ内の40MB(10,000ページ、4096バイト)
ipcs -mu
、。
500MBの用途についてもう少し積極的に説明したい!総GEMクォータを表示する方法はありますか? (または他の可能な貢献者)。
Intelグラフィックハードウェアでグラフィックデスクトップを実行しているので、いくつかのGEMを割り当ててほしいです。私のカーネルバージョンは4.18.16-200.fc28.x86_64
(Fedora Workstation 28)です。
答え1
これはフローチャートに次のように表示されます。「drm mmオブジェクト」または「i915」。/proc/<pid>/maps
GEM / DRMを使用しているプロセスのPIDを見ると、次のようになります。
awk '/(drm mm object)|i915/ { hypidx = index($1, "-"); from = substr($1, 1, hypidx - 1); to = substr($1, hypidx + 1); sum += strtonum("0x" to) - strtonum("0x" from) } END { print sum }' /proc/${PID}/maps
割り当てられたGEMバッファの合計サイズが表示されます。合計は、rootユーザーとして「drm mm object」または「i915」を1回以上入力することによって計算できます。
find /proc -maxdepth 2 -name maps |
xargs grep -E -l "(drm mm object)|i915" |
xargs awk '/(drm mm object)|i915/ { hypidx = index($1, "-"); sum += strtonum("0x" substr($1, hypidx + 1)) - strtonum("0x" substr($1, 1, hypidx - 1)) } END { print sum }'
(-maxdepth 2
スレッドマップを見るのを避ける必要があります)。いくつかの追加のinodeベースの重複排除が必要な場合があります。
答え2
編集:カーネルのデバッグ目的にのみ使用されるインターフェイスがあります。アクセスのみ可能root
で不安定です。カーネル開発者でない場合は、上書き、名前変更、または方向が正しく指定されていない可能性があります。 (私が知っているのは欠陥があるかもしれません。)しかし、問題が発生した場合、問題が存在することを知っておくと便利です。
運転i915
手が提供した情報は次のとおりです。
$ sudo sh -c 'cat /sys/kernel/debug/dri/*/i915_gem_objects'
643 objects, 205852672 bytes
75 unbound objects, 7811072 bytes
568 bound objects, 198041600 bytes
16 purgeable objects, 5750784 bytes
16 mapped objects, 606208 bytes
13 huge-paged objects (2M, 4K) 123764736 bytes
13 display objects (globally pinned), 14954496 bytes
4294967296 [0x0000000010000000] gtt total
Supported page sizes: 2M, 4K
[k]contexts: 16 objects, 548864 bytes (0 active, 548864 inactive, 548864 global, 0 shared, 0 unbound)
systemd-logind: 324 objects, 97374208 bytes (0 active, 115798016 inactive, 23941120 global, 5246976 shared, 3858432 unbound)
Xwayland: 24 objects, 6995968 bytes (0 active, 12169216 inactive, 5283840 global, 5246976 shared, 110592 unbound)
gnome-shell: 246 objects, 89739264 bytes (26517504 active, 120852480 inactive, 63016960 global, 5242880 shared, 3629056 unbound)
Xwayland: 25 objects, 17309696 bytes (0 active, 22503424 inactive, 5304320 global, 5242880 shared, 90112 unbound)
もう一度注意して進めてください。mapped objects
600KBのみ表示されることを確認しました。mapped
ここでの意味は、私が予想したものとは異なるようです。比較のために、次のPythonスクリプトを実行してユーザープロセスのアドレス空間にマップされたi915オブジェクトを表示すると、合計70MBが表示されます。
私の出力の行は、別の仮想コンソールで実行されているsystemd-logind
2番目のインスタンスを表します。gnome-shell
テキストログインを実行している仮想コンソールに切り替えると、このファイルには2systemd-logind
行しか表示されませんが、何も表示されませんgnome-shell
。 :-).
/proc/*/fd/
そうでない場合の最善の方法は、および/proc/*/map_files/
(または)で開いているすべてのファイルを検索していくつかのshmemファイルを見つけることです/proc/*/maps
。
正しい技術を使用すると、どのファイルが隠されたshmemファイルシステムに属しているかを確実に識別することが可能になります。
各共有メモリオブジェクトは名前のファイルです。これらの名前は、ファイルを生成したカーネルサブシステムを識別するために使用できます。
- SYSV00000000
- i915 (例: Intel GPU)
- memfd:gdk-wayland
- 開発/ゼロ(「匿名」共有マッピングの場合)
- ...
問題はこれが本当だということだ。いいえすべてのDRM / GEM割り当てを表示します。 DRMバッファは、デジタルハンドルのようにマッピングなしで存在できます。これは、作成時に使用されたオープンDRMファイルに関連付けられます。プログラムがクラッシュまたはシャットダウンすると、DRMファイルが閉じられ、すべてのDRMハンドルが自動的にクリーンアップされます。 (他のソフトウェアがファイル記述子のコピーを開いていない限り、この古いバグのように.)
https://www.systutorials.com/docs/linux/man/7-drm-gem/
で開いたDRMファイルが見つかりますが、/proc/*/fd/
ブロックが割り当てられていないサイズが0のファイルとして表示されます。
たとえば、次の出力は50%/ 300 MBを超えることができないシステムを示していますShmem
。
$ grep Shmem: /proc/meminfo
Shmem: 612732 kB
$ df -h -t tmpfs
Filesystem Size Used Avail Use% Mounted on
tmpfs 3.9G 59M 3.8G 2% /dev/shm
tmpfs 3.9G 2.5M 3.9G 1% /run
tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
tmpfs 3.9G 9.0M 3.9G 1% /tmp
tmpfs 786M 20K 786M 1% /run/user/42
tmpfs 786M 8.0M 778M 2% /run/user/1000
tmpfs 786M 5.7M 781M 1% /run/user/1001
$ sudo ipcs -mu
------ Shared Memory Status --------
segments allocated 20
pages allocated 4226
pages resident 3990
pages swapped 0
Swap performance: 0 attempts 0 successes
shmem ファイルシステムで開いているすべてのファイルを非表示にします。
$ sudo python3 ~/shm -s
15960 /SYSV*
79140 /i915
7912 /memfd:gdk-wayland
1164 /memfd:pulseaudio
104176
ログインした2人のGNOMEユーザーの1人をログアウトする前と後は、次のようになります。これはgnome-shell
、マップされていないDRMバッファが100MBを超えると発生する可能性があります。
$ grep Shmem: /proc/meminfo
Shmem: 478780 kB
$ df -t tmpfs -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 3.9G 4.0K 3.9G 1% /dev/shm
tmpfs 3.9G 2.5M 3.9G 1% /run
tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
tmpfs 3.9G 276K 3.9G 1% /tmp
tmpfs 786M 20K 786M 1% /run/user/42
tmpfs 786M 8.0M 778M 2% /run/user/1000
tmpfs 786M 5.7M 781M 1% /run/user/1001
$ sudo ./shm -s
80 /SYSV*
114716 /i915
1692 /memfd:gdk-wayland
1156 /memfd:pulseaudio
117644
$ grep Shmem: /proc/meminfo
Shmem: 313008 kB
$ df -t tmpfs -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 3.9G 4.0K 3.9G 1% /dev/shm
tmpfs 3.9G 2.1M 3.9G 1% /run
tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
tmpfs 3.9G 204K 3.9G 1% /tmp
tmpfs 786M 20K 786M 1% /run/user/42
tmpfs 786M 6.8M 780M 1% /run/user/1000
$ sudo ./shm -s
40 /SYSV*
88496 /i915
1692 /memfd:gdk-wayland
624 /memfd:pulseaudio
90852
上記の出力を生成するために使用されたPythonスクリプト:
#!/bin/python3
# Reads Linux /proc. No str, all bytes.
import sys
import os
import stat
import glob
import collections
import math
# File.
# 'name' is first name encountered, we don't track hardlinks.
Inode = collections.namedtuple('Inode', ['name', 'bytes', 'pids'])
# inode number -> Inode object
inodes = dict()
# pid -> program name
pids = dict()
# filename -> list() of Inodes
filenames = dict()
def add_file(pid, proclink):
try:
vfs = os.statvfs(proclink)
# The tmpfs which reports 0 blocks is an internal shm mount
# python doesn't admit f_fsid ...
if vfs.f_blocks != 0:
return
filename = os.readlink(proclink)
# ... but all the shm files are deleted (hack :)
if not filename.endswith(b' (deleted)'):
return
filename = filename[:-10]
# I tried a consistency check that all our st_dev are the same
# but actually there can be more than one internal shm mount!
# i915 added a dedicated "gemfs" so they could control mount options.
st = os.stat(proclink)
# hack the second: ignore deleted character devices from devpts
if stat.S_ISCHR(st.st_mode):
return
# Read process name succesfully,
# before we record file owned by process.
if pid not in pids:
pids[pid] = open(b'/proc/' + pid + b'/comm', 'rb').read()[:-1]
if st.st_ino not in inodes:
inode_pids = set()
inode_pids.add(pid)
inode = Inode(name=filename,
bytes=st.st_blocks * 512,
pids=inode_pids)
inodes[st.st_ino] = inode
else:
inode = inodes[st.st_ino]
inode.pids.add(pid)
# Group SYSV shared memory objects.
# There could be many, and the rest of the name is just a numeric ID
if filename.startswith(b'/SYSV'):
filename = b'/SYSV*'
filename_inodes = filenames.setdefault(filename, set())
filename_inodes.add(st.st_ino)
except FileNotFoundError:
# File disappeared (race condition).
# Don't bother to distinguish "file closed" from "process exited".
pass
summary = False
if sys.argv[1:]:
if sys.argv[1:] == ['-s']:
summary = True
else:
print("Usage: {0} [-s]".format(sys.argv[0]))
sys.exit(2)
os.chdir(b'/proc')
for pid in glob.iglob(b'[0-9]*'):
for f in glob.iglob(pid + b'/fd/*'):
add_file(pid, f)
for f in glob.iglob(pid + b'/map_files/*'):
add_file(pid, f)
def pid_name(pid):
return pid + b'/' + pids[pid]
def kB(b):
return str(math.ceil(b / 1024)).encode('US-ASCII')
out = sys.stdout.buffer
total = 0
for (filename, filename_inodes) in sorted(filenames.items(), key=lambda p: p[0]):
filename_bytes = 0
for ino in filename_inodes:
inode = inodes[ino]
filename_bytes += inode.bytes
if not summary:
out.write(kB(inode.bytes))
out.write(b'\t')
#out.write(str(ino).encode('US-ASCII'))
#out.write(b'\t')
out.write(inode.name)
out.write(b'\t')
out.write(b' '.join(map(pid_name, inode.pids)))
out.write(b'\n')
total += filename_bytes
out.write(kB(filename_bytes))
out.write(b'\t')
out.write(filename)
out.write(b'\n')
out.write(kB(total))
out.write(b'\n')