我在ARM上的嵌入式Linux中运行了两个相对较大的应用程序(进程),具有3个RAM库(在Linux cmdline中:mem = 128M mem = 256M @ 0x90000000 mem = 128M @ 0xA0000000)。 一个应用程序处理用户命令,在这些命令之间可能存在运行普通Linux shell命令的请求。这实现为:
if((fp=popen(UserCommand, "r")) == NULL) return(errno));
fgets(ReplyString, 128, fp);
Res = pclose(fp);
第一行返回errno = 12 - ENOMEM,即使是最简单的命令,如" pwd",尽管有足够的内存:
root@dm814x-evm:~# free
total used free shared buffers
Mem: 461472 38576 422896 0 152
Swap: 0 0 0
Total: 461472 38576 422896
据我所知,有超过400MB的可用空间!
为了第一个测试目的,我也取消了第二个过程 - 操作!,错误已经消失!!!
对于第二个测试,我运行telnet并通过它执行命令(当两个进程都在运行时) - 没问题,工作正常。
那么,捕获的位置在哪里?
答案 0 :(得分:4)
如果用fork()
实现popen(因为它目前在glibc中)而不是posix_spawn()
或vfork()
,那么你需要的内存与父进程使用的内存一样多成功。如果禁用系统上的过度使用,此分配可能会失败,因此要解决您的问题,您应该执行以下操作之一:
完全启用系统上的过度使用
sudo sh -c 'echo 1>/proc/sys/vm/overcommit_memory'
执行popen
自己做的事情,但用pipe()
和posix_spawn()
来表达,而不是经典的pipe()
,dup2()
,{ {1}},fork()
组合。
(execve()
1)创建一个管道2)将管道的一端包裹在popen
中,然后3)创建一个过程并将管道的另一端连接到过程的{{1 }或FILE
,将进程的stdin
保存在stdout
结构中
经典pid
+ FILE
进程创建方式的问题在于,如果禁用overcommit,fork()
必须是悲观的,并假设子进程可能继续运行父进程,这意味着孩子需要父母记忆的每一页。启用过度使用后,内存将被借用,并且只有在访问借来的内存时才会出现问题(内存不足的杀手)(如果进程很快就会调用execve()
,则不会出现问题)。禁用过度使用时,必须保留所有内存,这就是为什么如果fork()
调用来自更大的进程,它可能会失败。