- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
考虑以下程序:
#include <sys/mman.h>
#include <stdlib.h>
#include <errno.h>
int
main()
{
errno = 0;
mlockall(MCL_FUTURE);
char *a = malloc(1);
if (!a)
exit(errno);
munlockall();
exit(0);
}
当以普通用户身份运行时,我得到:
~ ./a.out
~ echo $?
11
来自 /usr/include/asm-generic/errno-base.h
:
#define EAGAIN 11 /* Try again */
当以 root 身份运行它或传递 MCL_FUTURE | 时MCL_CURRENT
它运行成功。我假设权限不足或标志错误,但 EPERM 和 EINVAL 均未返回。
这两个函数的手册页中均未指定该错误,mlockall 的 POSIX 规范中也未指定。在 mlockall 之后放置一个 printf 表明是 malloc 在设置 errno。
更奇怪的是,malloc 似乎没有设置 EAGAIN(或者我找错地方了):
/usr/src/glibc/glibc-2.19/malloc grep -r . -e EAGAIN
这是怎么回事?
~ uname -r 18:15:04
3.16-2-486
~ gcc --version 18:15:05
gcc (Debian 4.9.2-10) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
~ ldd --version 18:15:11
ldd (Debian GLIBC 2.19-18+deb8u1) 2.19
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.
~ 18:15:15
最佳答案
您的 mlockall()
调用要求锁定所有 future 的内存分配。但是,操作系统设置了可以被任何一个非特权进程锁定的最大内存量。您可以使用 getrlimit(RLIMIT_MEMLOCK,...)
查询此数量。在我的系统上它是 65536 字节。
现在,当我在我的系统上运行您的程序时,使用 strace(1)
查看进行了哪些系统调用,我得到以下信息:
mlockall(MCL_FUTURE) = 0
brk(0) = 0x2318000
brk(0x2339000) = 0x2318000
mmap(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 EAGAIN (Resource temporarily unavailable)
mmap(NULL, 134217728, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 EAGAIN (Resource temporarily unavailable)
mmap(NULL, 67108864, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 EAGAIN (Resource temporarily unavailable)
mmap(NULL, 134217728, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 EAGAIN (Resource temporarily unavailable)
mmap(NULL, 67108864, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 EAGAIN (Resource temporarily unavailable)
exit_group(11) = ?
所以malloc
首先使用brk
尝试分配135168字节(0x2339000-0x2318000
)。这失败了,因为它超过了锁定限制,因此 brk
保留“断点”(进程数据段的顶部)不变。 (请参阅 brk(2)
手册页中有关 brk()
的 C 库和内核版本之间的不同约定的说明。)
malloc
然后尝试使用 mmap
分配 1048576 字节。这也失败了(因为它超过了 65536 字节),在这里我们看到返回了 EAGAIN
错误代码。 mmap(2)
的手册页记录了将 errno
设置为 EAGAIN
如果“文件已被锁定,或内存过多锁定”,后者正是这里的情况。 malloc
,像许多库函数一样,将通过它进行的系统调用留下的 errno
值,所以 EAGAIN
是您在 malloc
返回。
(带有 PROT_NONE
的额外 mmap
调用似乎是为了保留一些地址空间供将来使用,并帮助确保将来的分配以适当的方式对齐。请参阅 glibc 源代码中的 malloc/arena.c
以获取详细信息。在这种情况下它们也失败了,但这不是那么相关。)
简而言之,问题是 malloc
试图向操作系统请求比您(用户)请求的内存量大得多的内存。这是为了提高效率,因为在大多数情况下,您将继续分配更多的小内存块,并且您不想为每个内存块进行系统调用。但是这个数量超过了锁定内存的限制,所以它失败了。 EAGAIN
是本例中 mmap
系统调用设置的错误代码。
也许 malloc
手册页应该提到这个可能的 errno
设置,但更常见的是高级库函数不描述所有可能的方式 errno
可以由底层系统调用设置。 (例如,fprintf(3)
调用 write(2)
,如果磁盘已满,但您不会在 fprintf(3)
手册页中找到任何提及。)您应该知道。
如果您想使用mlockall(MCL_FUTURE)
,那么您可能无法计划使用malloc(3)
分配内存。您必须从 sbrk(2)
或 mmap(2)
手动获取它,当然,要计划将其保持在适当的限制下或优雅地失败。这是非常不方便和限制性的,所以如果您需要一些锁定的内存,并且您不是 root,您可能只想对足够小的对象使用 mlock(2)
。
关于c - malloc 将 errno 设置为 EAGAIN,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34165276/
我删除数据库失败: mysql> 删除数据库 mydb; 错误 1010 (HY000):删除数据库时出错(不能 rmdir './mydb',errno: 39) 目录 db/mydb 存在于 my
据我所知,python的异常返回的errnos大部分与“linux/errno.h”中的errnos相同。但有时,事情并不像我期望的那样: 例如,当一个socket连接抛出一个socket.timeo
我们是否需要在调用函数之前将errno 重置为零?请参见下面的代码。现在的场景是 a_dest_path 是一个现有目录。但是当我执行代码时,它总是尝试 mkdir 但返回错误说该目录无法创建,因为它
在Red Hat Enterprise Linux Server release 5.7 上配置YUM本地源时,遇到了"[Errno 5] OSError: [Errno 2] No su
我正在尝试制作在线FPS游戏,到目前为止,它可以在我的本地网络上运行。我正在尝试做的是使其在全局范围内运作 过去,我曾尝试过使其他Python项目在全局范围内工作,但到目前为止,我还无法使其正常工作。
我希望获得有关在 Python 2.7 中使用urlopen时出现IOError: [Errno socket error] [Errno 10060]的更多信息。我正在使用我的个人 35MB/s 互
来自 linux 中 fwrite 的手册页, 描述 函数 fread() 从 stream 指向的流中读取数据的 nmemb 元素,每个 size 字节长,并将它们存储在 ptr 给定的位置。
我试图了解 glibc 如何在预处理器不替换 errno 符号的情况下初始化 errno。 我首先尝试自己基于csu/errno-loc.c实现了一个简单的版本和 csu/errno.c : myer
我看过这段代码: #if !defined(errno) extern int errno; #endif 所以我的问题是 errno 是 int 还是 macro ,因为使用 #if if 可以检查
errno.h 中的这 2 个 linux 错误有什么区别? 23 和 24 我尝试了 2 个不同的网站,但无法理解两者之间的区别。 [EMFILE] Too many open files. [EN
操作系统:Oracle Linux 6 [xxx@host /etc]$ uname -a Linux slc08yld 2.6.39-400.298.2.el5uek #1 SMP Mon Jan
什么样的库函数所面临的什么样的错误会影响errno并将其设置为非零值?在我下面的程序中,我打算使用 if(errno!=0) 作为条件来检查我使用的库函数是否正常运行,这是我发现的(见下面的代码):
我有一个 python 脚本,它创建一个 tar 文件,将文件移动到 tar 文件中,然后删除它们。 我可以毫无问题地手动运行脚本。但是当它从 cron 运行时,它失败了: IOError: [Err
我已经安装了 TensorFlow。当我下载 MNISTdataset 时,存在一个错误。谁能告诉我出了什么问题?非常感谢!错误详情如下: Python 2.7.9 (default, Apr 2
我正在尝试运行我的 python 代码,它显示以下内容: IOError: [Errno socket error] [Errno 54] Connection reset by peer 这是我的代
我正在将大量金融时间序列数据写入单个 CSV 文件。在一个实例中,我发现 to_csv 方法反复失败,但我终生无法弄清楚原因。在调用 to_csv 方法期间,一切都会挂起 10-15 分钟以上。在因错
我正在尝试从我的Python脚本打开文件recentlyUpdated.yaml。但当我尝试使用时:。我收到一个错误,内容是:。为什么?我怎样才能解决这个问题?
我正在尝试从我的Python脚本打开文件recentlyUpdated.yaml。但当我尝试使用时:。我收到一个错误,内容是:。为什么?我怎样才能解决这个问题?
我正在尝试从我的Python脚本打开文件recentlyUpdated.yaml。但当我尝试使用时:。我收到一个错误,内容是:。为什么?我怎样才能解决这个问题?
请解释以下程序中发生了什么。 我在程序的开头和结尾检查了 strerror(errno) 返回的地址,并确认它每次都返回相同的地址。然后一旦确定这一点,在第一种情况下我继续将相同的地址分配给 ptr,
我是一名优秀的程序员,十分优秀!