我想根据可用内存分配缓冲区。这样,当我进行处理和内存使用量增加时,仍然保持可用的内存限制。有没有办法获得可用的内存(我不知道虚拟或物理内存状态会有什么不同?)。方法必须是平台独立的,因为它将用于Windows,OS X,Linux和AIX。 (如果可能的话,我还想为我的应用程序分配一些可用内存,在执行期间它不会改变。)
编辑:我用可配置的内存分配做到了。 我理解这不是一个好主意,因为大多数操作系统为我们管理内存,但我的应用程序是一个ETL框架(旨在用于服务器,但也在桌面上用作Adobe indesign的插件)。因此,我正在运行以发布因为而不是使用交换,Windows将返回错误的alloc,其他应用程序开始失败。当我被教导避免崩溃等等时,只是试图优雅地降级。
答案 0 :(得分:132)
在类UNIX操作系统上,有sysconf。
#include <unistd.h>
unsigned long long getTotalSystemMemory()
{
long pages = sysconf(_SC_PHYS_PAGES);
long page_size = sysconf(_SC_PAGE_SIZE);
return pages * page_size;
}
在Windows上,有GlobalMemoryStatusEx
:
#include <windows.h>
unsigned long long getTotalSystemMemory()
{
MEMORYSTATUSEX status;
status.dwLength = sizeof(status);
GlobalMemoryStatusEx(&status);
return status.ullTotalPhys;
}
所以,只要做一些花哨的#ifdef
,你就会好起来。
答案 1 :(得分:29)
有理由希望在HPC中为科学软件执行此操作。 (不是游戏,网络,商业或嵌入式软件)。科学软件通常会经历数TB的数据来完成一次计算(或运行)(并运行数小时或数周) - 所有这些都无法存储在内存中(如果有一天你告诉我一个太字节是任何PC的标准配置)或平板电脑或手机将是科学软件预计将处理数PB或更多的情况)。内存量也可以决定有意义的方法/算法类型。用户并不总是想要决定记忆和方法 - 他/她还有其他需要担心的事情。因此,程序员应该很好地了解可用的内容(4Gb或8Gb或64Gb或者这些天),以确定方法是自动工作还是选择更费力的方法。使用磁盘但最好使用内存。并且不鼓励这类软件的用户在运行这样的软件时在他们的计算机上做太多事情 - 事实上,他们经常使用专用的机器/服务器。
答案 2 :(得分:13)
通过阅读这些答案,我惊讶于很多人认为OP的计算机内存属于其他人。这是他的计算机和他的内存,因为他认为合适,即使它打破了其他系统提出索赔。这是一个有趣的问题。在一个更原始的系统上我有memavail()
告诉我这个。为什么OP不能在不扰乱其他系统的情况下占用尽可能多的内存?
这是一个分配不到一半可用内存的解决方案,只是为了善待。输出是:
必填FFFFFFFF
必填7FFFFFFF
必填3FFFFFFF
分配的内存大小= 1FFFFFFF
#include <stdio.h>
#include <stdlib.h>
#define MINREQ 0xFFF // arbitrary minimum
int main(void)
{
unsigned int required = (unsigned int)-1; // adapt to native uint
char *mem = NULL;
while (mem == NULL) {
printf ("Required %X\n", required);
mem = malloc (required);
if ((required >>= 1) < MINREQ) {
if (mem) free (mem);
printf ("Cannot allocate enough memory\n");
return (1);
}
}
free (mem);
mem = malloc (required);
if (mem == NULL) {
printf ("Cannot enough allocate memory\n");
return (1);
}
printf ("Memory size allocated = %X\n", required);
free (mem);
return 0;
}
答案 3 :(得分:11)
没有独立于平台的方法,不同的操作系统使用不同的内存管理策略。
这些其他堆栈溢出问题将有所帮助:
你应该注意:在Linux中获得可用内存的“真实”价值是非常困难的。操作系统显示的进程使用的内容并不能保证实际为进程分配的内容。
这是开发嵌入式Linux系统(如路由器)时的常见问题,您希望在其中尽可能多地缓冲硬件。这是一个示例链接,显示如何在linux(C)中获取此信息:
答案 4 :(得分:5)
使用sysctl(man 3 sysctl
)的Mac OS X示例:
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/sysctl.h>
int main(void)
{
int mib[2] = { CTL_HW, HW_MEMSIZE };
u_int namelen = sizeof(mib) / sizeof(mib[0]);
uint64_t size;
size_t len = sizeof(size);
if (sysctl(mib, namelen, &size, &len, NULL, 0) < 0)
{
perror("sysctl");
}
else
{
printf("HW.HW_MEMSIZE = %llu bytes\n", size);
}
return 0;
}
(也可以在其他类似BSD的操作系统上运行?)
答案 5 :(得分:3)
此的“官方”功能为std::get_temporary_buffer()
。但是,您可能希望测试您的平台是否具有良好的实现。我知道并非所有平台都能按预期运行。
答案 6 :(得分:3)
下面的代码给出了以MB为单位的总内存和可用内存。适用于FreeBSD,但你应该能够在你的平台上使用相同/类似的sysctl可调参数并做同样的事情(Linux和OS X至少有sysctl)
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/vmmeter.h>
int main(){
int rc;
u_int page_size;
struct vmtotal vmt;
size_t vmt_size, uint_size;
vmt_size = sizeof(vmt);
uint_size = sizeof(page_size);
rc = sysctlbyname("vm.vmtotal", &vmt, &vmt_size, NULL, 0);
if (rc < 0){
perror("sysctlbyname");
return 1;
}
rc = sysctlbyname("vm.stats.vm.v_page_size", &page_size, &uint_size, NULL, 0);
if (rc < 0){
perror("sysctlbyname");
return 1;
}
printf("Free memory : %ld\n", vmt.t_free * (u_int64_t)page_size);
printf("Available memory : %ld\n", vmt.t_avm * (u_int64_t)page_size);
return 0;
}
以下是程序的输出,与我系统上的vmstat(8)输出进行比较。
~/code/memstats % cc memstats.c
~/code/memstats % ./a.out
Free memory : 5481914368
Available memory : 8473378816
~/code/memstats % vmstat
procs memory page disks faults cpu
r b w avm fre flt re pi po fr sr ad0 ad1 in sy cs us sy id
0 0 0 8093M 5228M 287 0 1 0 304 133 0 0 112 9597 1652 2 1 97
答案 7 :(得分:1)
您是否考虑让用户配置缓冲区使用多少内存,而不是尝试猜测?这样你仍然可以在没有覆盖的情况下运行(可能稍微慢一点),但如果用户知道应用程序有可用的X内存,他们可以通过配置该数量来提高性能。
答案 8 :(得分:0)
Linux当前释放内存:sysconf(_SC_AVPHYS_PAGES)
和get_avphys_pages()
https://stackoverflow.com/a/2513561/895245的sysconf(_SC_PHYS_PAGES);
覆盖了总RAM。
sysconf(_SC_AVPHYS_PAGES)
和get_avphys_pages()
都是POSIX的glibc扩展,它们给出了当前可用的RAM页面总数。
然后,您只需将它们乘以sysconf(_SC_PAGE_SIZE)
即可获得当前的可用RAM。