1、使用ACE_Process派生进程
1.1 使用ACE_Process派生进程需要两个步骤:
- 实例化一个ACE_Process_Options对象,为新创建的进程指定属性:
- 设置标准I/O句柄(标准输入、标准输出、标准错误输出,可进行输入输出重定向);
- 指定父子进程句柄继承方式;
- 设置子进程的环境变量和命令行;
- 在Windows上设置安全属性,在UNIX上设置uid/gid/euid。
- 调用ACE_Process::spawn()方法派生新进程。
1.2 注意,ACE_Process::spawn()方法不是fork()
ACE_Process::spawn()方法类似于UNIX的system()调用,而不是fork()。如果我们非要使用fork(),可以调用ACE_OS::fork()。
1.3 ACE_Process::prepare()挂钩方法
一般情况下,我们可以先实例化一个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.4 ACE_Process其它挂钩方法
(1)parent (pid_t child),在fork()完成后,此挂钩方法会立刻在父进程中被回调;
(2)child (pid_t parent),在fork()完成后,后续的exec()被调用前,此挂钩方法会在子进程中被回调,此时新的环境还没有被设置。在Windows上这个函数不会被调用。
2、使用ACE_Process_Manager派生进程
2.1 ACE_Process_Manager提供的新特性
- ACE_Process_Manager允许用户通过单次spawn_n()调用派生多个进程。
- ACE_Process_Manager有子进程计数,因此可以通过不带参数的wait()调用等待所有子进程。
- 可以通过调用terminate(pid_t child_pid)强制终止某个子进程。
- 能够与ACE_Reactor框架协同工作。
2.2 ACE_Process_Manager的使用方法
与ACE_Process使用方法类似,首先实例化一个ACE_Process_Options对象,设置新进程属性,并将此对象传递给ACE_Process_Manager::spawn_n()方法,派生多个子进程。可以调用terminate()方法终止某个子进程,可以调用wait()等待某个或所有子进程。
2.3 ACE_Process_Manager与ACE_Reactor的集成
一般情况下,主进程创建子进程后,还需要完成自己的工作,不能单纯的调用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 ();
}
3、进程互斥锁ACE_Process_Mutex
进程间同步可以使用进程互斥锁类ACE_Process_Mutex。这个类提供了两个方法,acquire()和release(),分别用来获取或释放锁!