- 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/
我有一个程序从一个文件中读入,对输入进行一些处理,然后将它输出到一个套接字。一个多月以来它一直运行良好,突然我开始收到错误 11(EAGAIN?)错误,导致程序终止。当我启动程序的 32 个实例时,在
我有一个打开供读取的文件描述符,它可能是非阻塞的。我需要做的只是读取所有数据直到到达 EOF 并将该数据写入可写文件描述符。由于执行此复制的过程“不知道”周围发生的任何事情,我不认为我可以在等待数据时
所以,这是一个我有时看到但无法找出原因的奇怪案例。 我们有一个从常规文件读取的 C 程序。还有其他进程写入同一个文件。该应用程序基于这样一个事实,即写入在 Linux 中是原子的,写入大小高达 409
假设我有两个线程,主线程和一个专用于连续监听标准 TCP 套接字的线程。现在,说在某个时候我想关闭所有东西。从主线程,我想关闭监听线程正在处理的连接,然后加入线程并结束程序。 但是,这很棘手,因为我不
标题中的 EAGAIN 是什么意思? 最佳答案 EAGAIN在执行 non-blocking I/O 时经常被引发.这意味着“目前没有可用数据,稍后再试”。 它might (或 might not )
我在 Linux 上的一个项目使用阻塞套接字。事情发生得非常连续,所以非阻塞只会让事情变得更复杂。无论如何,我发现 recv() 调用经常返回 -1,其中 errno 设置为 EAGAIN。 man
尝试使用 pthread_create 生成线程时出现 EAGAIN。但是,根据我的检查,线程似乎已正确终止。 什么决定了操作系统在尝试使用 pthread_create 创建线程时给予 EAGAIN
我开发了一个 Android 应用程序,它有多个设备通过蓝牙套接字连接将数据发送回服务器设备,但是我遇到了错误: E/bt-btif: send none, EAGAIN or EWOULDBLOCK
我已经将 pthread 用于多线程程序,并且遇到了以下情况。当我在没有 sleep 命令的情况下运行代码时,它会在运行时导致错误,而当我添加 sleep 命令时,程序会按预期运行。 有 sleep
我正在 ubuntu linux 机器上用 c 编写客户端服务器套接字程序。服务器端需要处理很多连接,服务器和客户端都有一个本地套接字,在对它进行一些操作后将接收到的数据发送到本地进程,并且发送和接收
如果我在 Linux 中的非阻塞 tcp 套接字上使用 send(),除了发送缓冲区已满情况之外,它会返回 EAGAIN 吗? 我基本上需要决定是要将套接字发送缓冲区用作我的应用程序的唯一缓冲区,还是
我正在使用阻塞套接字来接受连接。我很少收到此错误,这使得调试变得困难。接受返回 EAGAIN 错误。这怎么可能是阻塞套接字? 最佳答案 如果套接字设置了接收超时(使用 SO_RCVTIMEO 套接字选
我实现了一个套接字客户端,通过 HTTP 与带有 RTSP 的网络摄像头通信,以从摄像头获取视频。 要与相机建立通信,首先我必须设置一个 HTTP-GET 隧道,然后发送 RTSP 命令。当相机失去连
我有一个通过 USB 接口(interface)的定制板。我正在编写 USB Linux 驱动程序。 当我在我的虚拟机上测试它时一切正常..但是当我切换到真实硬件并在硬件上使用 Yocto 并运行以下
我正在尝试学习如何使用 sigtimedwait(),但我发现它并没有等待超时完成。下面它似乎比它应该更快地返回 EAGAIN 4 秒(每 1 分钟超时快 1 秒): #include #inclu
我在通过以下方式打开的串行端口读取一些数据时遇到了一些问题。我已经多次使用这个代码实例并且一切正常,但是现在,由于某种我无法弄清楚的原因,我完全无法从串行端口读取任何内容。 我可以写,并且在另一端正确
我正在使用 QOpenGL 小部件绘制框架。但是,我正在努力使用 avcodec_receive_frame 获取帧。它在 else if (ret == AVERROR(EAGAIN)) block
我在 malloc() 上阅读了手册在 Solaris 中,发现 malloc()可以设置EAGAIN Solaris 中的错误。 手册写道: EAGAIN There is not enough m
我正在尝试用 C++ 创建一个 REQ Router Dealer REP 通信。子进程绑定(bind)路由器和经销商,路由器和经销商之间的代理,将 REP 连接到经销商并等待 zmq_recv
代码是这样的。在某些情况下,会返回eagain。 struct sigevent sev; sev.sigev_notify = SIGEV_THREAD_ID; sev._sigev_un._tid
我是一名优秀的程序员,十分优秀!