Я пытаюсь проанализировать значение PSS из /proc/<pid>/smaps
процесса в моем двоичном файле C++.
Согласно этому ответу SO, наивное чтение файла /proc/<pid>/smaps
, например, с помощью ifstream::getLine()
приведет к несогласованному набору данных. Предлагаемое решение состоит в том, чтобы использовать системный вызов read()
для чтения всех данных за один раз, например:
#include <unistd.h>
#include <fcntl.h>
...
char rawData[102400];
int file = open("/proc/12345/smaps", O_RDONLY, 0);
auto bytesRead = read(file, rawData, 102400); // this returns 3722 instead of expected ~64k
close(file);
std::cout << bytesRead << std::endl;
// do some parsing here after null-terminating the buffer
...
Моя проблема сейчас в том, что, несмотря на то, что я использую буфер размером 100 КБ, возвращается только 3722 байта. Глядя на то, что делает cat
при анализе файла с помощью strace, я вижу, что он использует несколько вызовов read()
(также получая около 3 КБ при каждом чтении), пока read()
не вернет 0 - как описано в документация read()
:
...
read(3, "7fa8db3d7000-7fa8db3d8000 r--p 0"..., 131072) = 3588
write(1, "7fa8db3d7000-7fa8db3d8000 r--p 0"..., 3588) = 3588
read(3, "7fa8db3df000-7fa8db3e0000 r--p 0"..., 131072) = 3632
write(1, "7fa8db3df000-7fa8db3e0000 r--p 0"..., 3632) = 3632
read(3, "7fa8db3e8000-7fa8db3ed000 r--s 0"..., 131072) = 3603
write(1, "7fa8db3e8000-7fa8db3ed000 r--s 0"..., 3603) = 3603
read(3, "7fa8db41d000-7fa8db425000 r--p 0"..., 131072) = 3445
write(1, "7fa8db41d000-7fa8db425000 r--p 0"..., 3445) = 3445
read(3, "7fff05467000-7fff05496000 rw-p 0"..., 131072) = 2725
write(1, "7fff05467000-7fff05496000 rw-p 0"..., 2725) = 2725
read(3, "", 131072) = 0
munmap(0x7f8d29ad4000, 139264) = 0
close(3) = 0
close(1) = 0
close(2) = 0
exit_group(0) = ?
+++ exited with 0 +++
Но разве это не должно давать противоречивые данные в соответствии с ответом SO, указанным выше?
Я также нашел некоторую информацию о proc здесь, которая, кажется, поддерживает предыдущий ответ SO:
Чтобы увидеть точный снимок момента, вы можете просмотреть файл /proc/‹pid›/smaps и отсканировать таблицу страниц.
Далее в тексте говорится:
Примечание: чтение /proc/PID/maps или /proc/PID/smaps по своей сути является колоритным (непротиворечивый вывод может быть достигнут только в одном вызове чтения). Обычно это проявляется при частичном чтении этих файлов во время изменения карты памяти. Несмотря на гонки, мы предоставляем следующие гарантии:
1) Сопоставленные адреса никогда не идут назад, что означает, что никакие два региона никогда не перекрываются.
2) Если есть что-то в данном vaddr в течение всей жизни smaps/maps walk, для этого будет какой-то вывод.
Поэтому мне кажется, что я могу доверять полученным данным только в том случае, если я получу их за один вызов read()
. Который возвращает только небольшой фрагмент данных, несмотря на то, что буфер достаточно велик. Что, в свою очередь, означает, что на самом деле нет способа получить непротиворечивый снимок /proc/<pid>/smaps
, а данные, возвращаемые cat/использованием нескольких вызовов read()
, могут быть мусором в зависимости от соотношения освещенности солнца и луны?
Или 2) на самом деле означает, что я слишком зациклен на предыдущем ответе SO, указанном выше?