ACE_Process::spawn()方法类似于UNIX的system()调用,而不是fork()。如果我们非要使用fork(),可以调用ACE_OS::fork()。
一般情况下,我们可以先实例化一个ACE_Process_Options对象,然后调用ACE_Process_Options::command_line()方法设置命令行。在调用ACE_Process::spawn()方法时把设置好的ACE_Process_Options对象传进去,派生子进程。代码如下:
ACE_Process_Options options; options.command_line ("/usr/bin/ls -l"); ACE_Process process; pid_t pid = process.spawn (options); process.wait ();
在创建新进程之前,ACE_Process::spawn()方法会调用进程对象的ACE_Process::prepare()挂钩方法。因此,如果不在外面设置新进程属性,我们也可以在ACE_Process::prepare()挂钩方法中初始化新进程属性。
ACE_Process::prepare()的返回值是有用的,如果返回0,则spawn()继续创建新进程,如果prepare()返回-1,spawn则放弃创建新进程。
(1)parent (pid_t child),在fork()完成后,此挂钩方法会立刻在父进程中被回调;
(2)child (pid_t parent),在fork()完成后,后续的exec()被调用前,此挂钩方法会在子进程中被回调,此时新的环境还没有被设置。在Windows上这个函数不会被调用。
与ACE_Process使用方法类似,首先实例化一个ACE_Process_Options对象,设置新进程属性,并将此对象传递给ACE_Process_Manager::spawn_n()方法,派生多个子进程。可以调用terminate()方法终止某个子进程,可以调用wait()等待某个或所有子进程。
一般情况下,主进程创建子进程后,还需要完成自己的工作,不能单纯的调用wait,阻塞的等待子进程的退出。通过与ACE_Reactor的集成,主进程在创建子进程后可继续自己的工作,在子进程退出时,再由Reactor框架通过调用ACE_Event_Handler::handle_exit (ACE_Process *process)完成子进程的资源回收。下面是一个例子:
#include <ace/Event_Handler.h> #include <ace/Reactor.h> #include <ace/Process_Manager.h> const int NCHILDREN = 10; // Handle child process exit class ProcessCleaner: public ACE_Event_Handler { public: ProcessCleaner (): count_(0) {} virtual int handle_exit (ACE_Process *process) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("[%d]Process %d exit with exit code %d\n"), count_, process->getpid (), process->return_value ())); if (++count_ == NCHILDREN) ACE_Reactor::instance ()->end_reactor_event_loop (); } private: int count_; }; int ACE_TMAIN (int argc, ACE_TCHAR *argv[]) { // Instantiate a process manager with space for // NCHILDREN processes. ACE_Process_Manager pm (NCHILDREN, ACE_Reactor::instance ()); // Create a child process exit handler. ProcessCleaner pc; // Specify the process options ACE_Process_Options options; options.command_line (ACE_TEXT ("/bin/date")); // Spawn NCHILDREN processes. pid_t pids[NCHILDREN]; pm.spawn_n (NCHILDREN, options, pids); // Register handler to be called when these processes eixt. for (int i = 0; i < NCHILDREN; i++) pm.register_handler (&pc, pids[i]); // Run the event loop ACE_Reactor::instance ()->run_reactor_event_loop (); }