utils/meminfo.cpp
utils/meminfo.cpp
Functions
Name | |
---|---|
long long | get_entry(const char * name, const char * buf) |
long long | get_entry_fatal(const char * name, const char * buf) |
long long | available_guesstimate(const char * buf) |
MemInfo | readMemInfo() |
Functions Documentation
function get_entry
static long long get_entry(
const char * name,
const char * buf
)
function get_entry_fatal
static long long get_entry_fatal(
const char * name,
const char * buf
)
function available_guesstimate
static long long available_guesstimate(
const char * buf
)
function readMemInfo
MemInfo readMemInfo()
Read some data from meminfo that is relevant to Syntalos.
Source code
/*
* Copyright (C) 2014 Jakob Unterwurzacher
* Copyright (C) 2019-2024 Matthias Klumpp <matthias@tenstral.net>
*
* SPDX-License-Identifier: MIT or LGPL-3.0-or-later
*
* Licensed under the GNU Lesser General Public License Version 3
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the license, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this software. If not, see <http://www.gnu.org/licenses/>.
*
* The MIT License (MIT)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "meminfo.h"
#include <QDebug>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
/* Parse the contents of /proc/meminfo (in buf), return value of "name"
* (example: MemTotal)
* Returns -errno if the entry cannot be found. */
static long long get_entry(const char *name, const char *buf)
{
const char *hit = strstr(buf, name);
if (hit == NULL) {
return -ENODATA;
}
errno = 0;
const long long val = strtoll(hit + strlen(name), NULL, 10);
if (errno != 0) {
int strtoll_errno = errno;
perror("get_entry: strtol() failed");
return -strtoll_errno;
}
return val;
}
/* Like get_entry(), but exit if the value cannot be found */
static long long get_entry_fatal(const char *name, const char *buf)
{
const long long val = get_entry(name, buf);
if (val < 0) {
qFatal("could not find entry '%s' in /proc/meminfo: %s", name, strerror((int)-val));
}
return val;
}
/* If the kernel does not provide MemAvailable (introduced in Linux 3.14),
* approximate it using other data we can get */
static long long available_guesstimate(const char *buf)
{
long long Cached = get_entry_fatal("Cached:", buf);
long long MemFree = get_entry_fatal("MemFree:", buf);
long long Buffers = get_entry_fatal("Buffers:", buf);
long long Shmem = get_entry_fatal("Shmem:", buf);
return MemFree + Cached + Buffers - Shmem;
}
MemInfo readMemInfo()
{
// Note that we do not need to close static FDs that we ensure to
// `fopen()` maximally once.
static FILE *fd;
// On Linux 5.3, "wc -c /proc/meminfo" counts 1391 bytes.
// 8192 should be enough for the foreseeable future.
char buf[8192] = {0};
MemInfo m = {0, 0, 0};
if (fd == NULL)
fd = fopen("/proc/meminfo", "r");
if (fd == NULL) {
qFatal("could not open /proc/meminfo: %s", strerror(errno));
}
rewind(fd);
size_t len = fread(buf, 1, sizeof(buf) - 1, fd);
if (ferror(fd)) {
qFatal("could not read /proc/meminfo: %s", strerror(errno));
}
if (len == 0) {
qFatal("could not read /proc/meminfo: 0 bytes returned");
}
m.memTotalKiB = get_entry_fatal("MemTotal:", buf);
long long MemAvailable = get_entry("MemAvailable:", buf);
if (MemAvailable < 0) {
// kernel was too old
MemAvailable = available_guesstimate(buf);
}
// Calculate percentages
m.memAvailablePercent = (double)MemAvailable * 100 / (double)m.memTotalKiB;
// Convert kiB to MiB
m.memAvailableMiB = MemAvailable / 1024;
return m;
}
Updated on 2025-07-10 at 23:28:57 +0000