In a process using lots of memory, how can I spawn a shell without a memory-hungry fork()?
On an embedded platform (with no swap partition), I have an application whose main process occupies most of the available physical memory. The problem is that I want to launch an external shell scr开发者_如何学运维ipt from my application, but using fork() requires that there be enough memory for 2x my original process before the child process (which will ultimately execl itself to something much smaller) can be created.
So is there any way to invoke a shell script from a C program without incurring the memory overhead of a fork()?
I've considered workarounds such as having a secondary smaller process which is responsible for creating shells, or having a "watcher" script which I signal by touching a file or somesuch, but I'd much rather have something simpler.
Some UNIX implementations will give you a vfork
(part of the Single UNIX spec) which is exactly like fork
except that it shares all the stuff with the parent.
With vfork
, there are a very limited number of things you can do in the child before calling exec
to overwrite the address space with another process - that's basically what vfork
was built for, a minimal copy version of fork
for the fork/exec
sequence.
If your system has an MMU, then usually fork()
is implemented using copy-on-write, which doesn't actually allocate more memory at the time fork()
is called. Additional memory would only be allocated if you write to any of the pages shared with the parent process. An exec()
would then discard those pages.
If you know you don't have an MMU, then perhaps fork()
is indeed implemented using an actual copy. Another approach might be to have a helper process that is responsible for spawning subshells, which you communicate with using a pipe.
I see you've already accepted an answer, but you may want to read about posix_spawn
and use if it if it's available on your target:
http://www.opengroup.org/onlinepubs/9699919799/functions/posix_spawn.html
It sounds as if the prudent move in this case is to port your shell script (if possible) to C, and executing it within the process; so you don't have to fork at all.
Then again; I don't know what you are actually trying to do.
Instead of forking your process to spawn a shell, launch a shell within your process (in foreground) then fork it within the shell.
system("/bin/ash /scripts/bgtask");
with /scripts/bgtask being:
/bin/ash /scripts/propertask &
This way you double only the memory used by the shell, not by the main program. Your main program goes busy for duration of spawning the two shells: original to start bgtask and the background clone launched by it, then the memory allocated by the first shell is free again.
精彩评论