linux下 system问题 高手进~ 100分

zxc345232435346 2009-08-04 05:22:24
最近遇到一个问题,我的一个linux进程(非常大,占用机器70%的内存),在进程运行过程中,我想执行一个shell命令,起初是调用system("shell命令"),但是system会fork一个子进程来完成这个操作,但是这时内存已经不够用(不足以复制出新的子进程), 请问各位牛人,怎么办,什么手段都行。
...全文
288 30 打赏 收藏 转发到动态 举报
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
晨星 2009-08-05
  • 打赏
  • 举报
回复
你的程序不能证明全局数组没有被拷贝。
顶多能证明你原来的程序,由于申请了大段堆内存,导致应用占用了更多的内存。而这个可能跟堆内存和静态区的分配机制不同有关。
zxc345232435346 2009-08-05
  • 打赏
  • 举报
回复
测试结果显示 ls 得到执行 也就是system成功了。
zxc345232435346 2009-08-05
  • 打赏
  • 举报
回复
我的测试代码;


#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <stdlib.h>

typedef unsigned long WORD32;
typedef unsigned char BYTE;

#define BSP_ERROR ((WORD32)(-1))
#define BSP_OK ( 0)


static char BUF[1073741824]="HI";
int main(void)
{
WORD32 *pdwTmp;
static int cnt=1;
int num;
pdwTmp = NULL;

char* args[] = { "/bin/ls", NULL };

memset(BUF,0,973741824);
while(cnt!=0)
{
sleep(3);
num=system("ls");
if(-1==num)
{
printf("fail to fork a child process %d\n",errno);
cnt=0;
}

}

}
zxc345232435346 2009-08-05
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 steedhorse 的回复:]
引用 13 楼 zxc381219 的回复:
还是不行啊 同志们,  vfork虽然在开始不会复制父进程内存,但是当使用exec时 vfork会copy-on-write 也就是还会去复制内存,仍然会内存不足!     

exec会替掉原来继承而来父进程内存image,怎么会这样呢。
是不是在vfork之后,你在子进程分支里,在执行exec之前还执行了别的语句,从名导致了copy-on-write了?
[/Quote]

不好意识 vfork+exec是没问题的 我上面说的错了,现在就是想搞清楚 为什么system时到底拷贝了什么东西 为什么全局数组没有被拷贝?
晨星 2009-08-05
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 zxc381219 的回复:]
是服务器程序 就那么大的       

问一下  为什么我的测试例子里  用malloc+memset占用系统大部分内存 system会失败,而用全局数组+memset占用系统大部分内存 system可以成功呢    system在fork子进程时 不会复制父进程的全局数组吗?  请指教
[/Quote]
这个涉及到加载器时的内存管理了,恐怕得研究内核代码才能完全搞清楚。
但理论上全局数组也是会“拷贝”的。
晨星 2009-08-05
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 zxc381219 的回复:]
还是不行啊 同志们,  vfork虽然在开始不会复制父进程内存,但是当使用exec时 vfork会copy-on-write 也就是还会去复制内存,仍然会内存不足!     
[/Quote]
exec会替掉原来继承而来父进程内存image,怎么会这样呢。
是不是在vfork之后,你在子进程分支里,在执行exec之前还执行了别的语句,从名导致了copy-on-write了?
zxc345232435346 2009-08-05
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 blackbillow 的回复:]
man vfork

It  is  rather  unfortunate  that  Linux  revived this specter(fork) from the past.

在2.6上,vfork已经没有存在的必要了

你应该重新考虑你那个占用70%内存的程序,设计上肯定有问题
[/Quote]



是服务器程序 就那么大的

问一下 为什么我的测试例子里 用malloc+memset占用系统大部分内存 system会失败,而用全局数组+memset占用系统大部分内存 system可以成功呢 system在fork子进程时 不会复制父进程的全局数组吗? 请指教
blackbillow 2009-08-05
  • 打赏
  • 举报
回复
It is rather unfortunate that Linux revived this specter(vfork) from the past.
blackbillow 2009-08-05
  • 打赏
  • 举报
回复
man vfork

It is rather unfortunate that Linux revived this specter(fork) from the past.

在2.6上,vfork已经没有存在的必要了

你应该重新考虑你那个占用70%内存的程序,设计上肯定有问题
zxc345232435346 2009-08-05
  • 打赏
  • 举报
回复
还有一个问题啊 我如果用malloc+memset把大部分内存占用 system时会失败 而用全局数组+memset把大部分内存占用,system依然会成功,也就是说system fork子进程时 拷贝内存不会拷贝全局内存

各位 是这样的吗? fork和vfork的拷贝区别 哪位能讲清楚些 谢谢啦~~~~~~~~~~~~~~
zxc345232435346 2009-08-05
  • 打赏
  • 举报
回复
还是不行啊 同志们, vfork虽然在开始不会复制父进程内存,但是当使用exec时 vfork会copy-on-write 也就是还会去复制内存,仍然会内存不足!
zxc345232435346 2009-08-05
  • 打赏
  • 举报
回复
ok 看来这个问题可以圆满解决了,等老大那边通过,就回来给兄弟们把分加上~
DarkChampion 2009-08-05
  • 打赏
  • 举报
回复
mark
zxc345232435346 2009-08-05
  • 打赏
  • 举报
回复
还没解决呢 先别沉啊~~ 顶上去
zxc345232435346 2009-08-05
  • 打赏
  • 举报
回复
调用system到底会不会复制父进程的东西呢?

我看到还有人自己写的my_system用vfork代替fork 号称这样不会复制没用的东西:


原文如下:


因为新fork出来的子进程会自动把父进程的数据段继承一份出来,如果父进程的数据段比较大的话,会占用较多的内存。建议自己做一个system函数,用vfork取代fork即可。

自己的system函数



int my_system(char* cmd)
{
intstatus = 0;
pid_t pid;

if ((pid = vfork())<0)
{
printf("vfork process error! \n");
status = -1;
}
else if (pid==0)
{
const char *new_argv[4];
struct sigaction sa_cld;
sa_cld.sa_handler = SIG_DFL;
sa_cld.sa_flags = 0;

/* 在子进程中放开SIGINT信号 */
sigemptyset(&sa_cld.sa_mask);
sigaction (SIGINT, &sa_cld, NULL);
sigaction (SIGQUIT, &sa_cld, NULL);

new_argv[0] = SHELL_NAME;
new_argv[1] = "-c";
new_argv[2] = cmd;
new_argv[3] = NULL;

if (execve(SHELL_PATH,(char *const *) new_argv, environ)<0)
{
printf("fail to execve %s! errno: %d\n",cmd,errno);
exit(1);
}
else
{
exit(0);
}
}
else
{
waitpid(pid,&status,0);
}

return status;
}




晨星 2009-08-05
  • 打赏
  • 举报
回复
哦,还真的是哈。:P
zxc345232435346 2009-08-05
  • 打赏
  • 举报
回复
int system(const char * cmdstring)
{
pid_t pid;
int status;

if(cmdstring == NULL){

return (1);
}


if((pid = fork())<0){

status = -1;
}
else if(pid == 0){
execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
-exit(127); //子进程正常执行则不会执行此语句
}
else{
while(waitpid(pid, &status, 0) < 0){
if(errno != EINTER){
status = -1;
break;
}
}
}
return status;
}

好像真的没有写啊 fork子进程成功之后立刻执行execl
晨星 2009-08-05
  • 打赏
  • 举报
回复
你对“写”的理解有点偏颇了。你看过“system”函数的实现代码吗?真的就连一条变量赋值语句都没有么?
只有exec系列才会马上替换掉父进程的内存image。——这同时也意味着传给exec的实参必需都是简单的表达式。
zxc345232435346 2009-08-05
  • 打赏
  • 举报
回复
奇怪的事发生了!!!!!!!!!!!!!

今天我又测试,低内存情况下调用system竟然没问题了

按说linux 不可能弱智到低内存就不能system,写时复制嘛 调用shell命令又没写 不会复制任何东西啊


大家说怎么回事啊 我快疯了
晨星 2009-08-04
  • 打赏
  • 举报
回复
比如:
const char cmd = "ls > a.txt";
execl("/bin/sh", "sh", "-c", cmd, (char*)0);
加载更多回复(10)

2,163

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 UNIX文化
社区管理员
  • UNIX文化社区
  • 文天大人
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧