ACE/FAQ/APG/Processes
Материал из Wiki.crossplatform.ru
Содержание |
[править] Process Manager Death
// $Id: Process_Manager_Death.cpp 94310 2011-07-09 19:10:06Z schmidt $ #include "ace/Log_Msg.h" #include "ace/Process_Manager.h" #include "ace/Reactor.h" static const int NCHILDREN = 2; // Listing 1 code/ch10 class DeathHandler: public ACE_Event_Handler { public: DeathHandler () : count_(0) { ACE_TRACE ("DeathHandler::DeathHandler"); } virtual int handle_exit (ACE_Process * process) { ACE_TRACE ("DeathHandler::handle_exit"); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Process %d exited with exit code %d\n"), process->getpid (), process->return_value ())); if (++count_ == NCHILDREN) ACE_Reactor::instance ()->end_reactor_event_loop (); return 0; } private: int count_; }; // Listing 1 // Listing 0 code/ch10 int ACE_TMAIN (int argc, ACE_TCHAR *argv[]) { if (argc > 1) // Running as a child. return 0; // Instantiate a process manager with space for // 10 processes. ACE_Process_Manager pm (10, ACE_Reactor::instance ()); // Create a process termination handler. DeathHandler handler; // Specify the options for the new processes to be spawned. ACE_Process_Options options; options.command_line (ACE_TEXT ("%s a"), argv[0]); // Spawn two child processes. pid_t pids[NCHILDREN]; pm.spawn_n (NCHILDREN, options, pids); // Register handler to be called when these processes exit. for (int i = 0; i < NCHILDREN; i++) pm.register_handler (&handler, pids[i]); // Run the reactor event loop waiting for events to occur. ACE_Reactor::instance ()->run_reactor_event_loop (); return 0; } // Listing 0
[править] Process Manager Spawn
// $Id: Process_Manager_Spawn.cpp 80826 2008-03-04 14:51:23Z wotte $ #include "ace/OS_NS_unistd.h" #include "ace/Log_Msg.h" // Listing 0 code/ch10 #include "ace/Process_Manager.h" static const int NCHILDREN = 2; int ACE_TMAIN (int argc, ACE_TCHAR *argv[]) { if (argc > 1) // Running as a child. { ACE_OS::sleep (10); } else // Running as a parent. { // Get the processwide process manager. ACE_Process_Manager* pm = ACE_Process_Manager::instance (); // Specify the options for the new processes // to be spawned. ACE_Process_Options options; options.command_line (ACE_TEXT ("%s a"), argv[0]); // Spawn two child processes. pid_t pids[NCHILDREN]; pm->spawn_n (NCHILDREN, options, pids); // Destroy the first child. pm->terminate (pids[0]); // Wait for the child we just terminated. ACE_exitcode status; pm->wait (pids[0], &status); // Get the results of the termination. #if !defined(ACE_WIN32) if (WIFSIGNALED (status) != 0) ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d died because of a signal ") ACE_TEXT ("of type %d\n"), pids[0], WTERMSIG (status))); #else ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("The process terminated with exit code %d\n"), status)); #endif /*ACE_WIN32*/ // Wait for all (only one left) of the // children to exit. pm->wait (0); } return 0; } // Listing 0
[править] Process Mutex
// $Id: Process_Mutex.cpp 95466 2012-01-20 19:31:23Z johnnyw $ #include "ace/OS_NS_unistd.h" #include "ace/Log_Msg.h" #include "ace/Process.h" #include "ace/Process_Mutex.h" // Listing 1 code/ch10 class GResourceUser { public: GResourceUser (ACE_Process_Mutex &mutex) : gmutex_(mutex) { ACE_TRACE ("GResourceUser::GResourceUser"); } void run (void) { ACE_TRACE ("GResourceUser::run"); int count = 0; while (count++ < 10) { int result = this->gmutex_.acquire (); ACE_TEST_ASSERT (result == 0); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P| %t) has the mutex\n"))); // Access Global resource ACE_OS::sleep (1); result = this->gmutex_.release (); ACE_TEST_ASSERT (result == 0); ACE_OS::sleep (1); // Give other process a chance. } } private: ACE_Process_Mutex &gmutex_; }; // Listing 1 // Listing 0 code/ch10 int ACE_TMAIN (int argc, ACE_TCHAR *argv[]) { if (argc > 1) // Run as the child. { // Create or get the global mutex. ACE_Process_Mutex mutex ("GlobalMutex"); GResourceUser acquirer (mutex); acquirer.run (); } else // Run as the parent. { ACE_Process_Options options; options.command_line (ACE_TEXT ("%s a"), argv[0]); ACE_Process processa, processb; pid_t pida = processa.spawn (options); pid_t pidb = processb.spawn (options); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Spawned processes; pids %d:%d\n"), pida, pidb)); if (processa.wait() == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("processa wait")), -1); if (processb.wait() == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("processb wait")), -1); } return 0; } // Listing 0
[править] Spawn
// $Id: Spawn.cpp 80826 2008-03-04 14:51:23Z wotte $ #include "ace/OS_NS_stdio.h" #include "ace/OS_NS_fcntl.h" #include "ace/OS_NS_pwd.h" #include "ace/os_include/os_pwd.h" #include "ace/OS_NS_stdlib.h" #include "ace/OS_NS_string.h" #include "ace/OS_NS_unistd.h" #include "ace/OS_NS_pwd.h" #include "ace/Process.h" #include "ace/Log_Msg.h" // Listing 1 code/ch10 class Manager : public ACE_Process { public: Manager (const ACE_TCHAR* program_name) { ACE_TRACE ("Manager::Manager"); ACE_OS::strcpy (programName_, program_name); } int doWork (void) { ACE_TRACE ("Manager::doWork"); // Spawn the new process; prepare() hook is called first. ACE_Process_Options options; pid_t pid = this->spawn (options); if (pid == ACE_INVALID_PID) ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("spawn")), -1); // Wait forever for my child to exit. if (this->wait () == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("wait")), -1); // Dump whatever happened. this->dumpRun (); return 0; } // Listing 1 private: // Listing 3 code/ch10 int dumpRun (void) { ACE_TRACE ("Manager::dumpRun"); if (ACE_OS::lseek (this->outputfd_, 0, SEEK_SET) == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("lseek")), -1); char buf[1024]; ssize_t length = 0; // Read the contents of the error stream written // by the child and print it out. while ((length = ACE_OS::read (this->outputfd_, buf, sizeof(buf)-1)) > 0) { buf[length] = 0; ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%C\n"), buf)); } ACE_OS::close (this->outputfd_); return 0; } // Listing 3 // Listing 2 code/ch10 // prepare() is inherited from ACE_Process. int prepare (ACE_Process_Options &options) { ACE_TRACE ("Manager::prepare"); options.command_line (ACE_TEXT ("%s 1"), this->programName_); if (this->setStdHandles (options) == -1 || this->setEnvVariable (options) == -1) return -1; #if !defined (ACE_WIN32) && !defined (ACE_LACKS_PWD_FUNCTIONS) return this->setUserID (options); #else return 0; #endif } int setStdHandles (ACE_Process_Options &options) { ACE_TRACE ("Manager::setStdHandles"); ACE_OS::unlink ("output.dat"); this->outputfd_ = ACE_OS::open ("output.dat", O_RDWR | O_CREAT); return options.set_handles (ACE_STDIN, ACE_STDOUT, this->outputfd_); } int setEnvVariable (ACE_Process_Options &options) { ACE_TRACE ("Manager::setEnvVariables"); return options.setenv (ACE_TEXT ("PRIVATE_VAR=/that/seems/to/be/it")); } // Listing 2 #if !defined (ACE_LACKS_PWD_FUNCTIONS) // Listing 10 code/ch10 int setUserID (ACE_Process_Options &options) { ACE_TRACE ("Manager::setUserID"); passwd* pw = ACE_OS::getpwnam ("nobody"); if (pw == 0) return -1; options.seteuid (pw->pw_uid); return 0; } // Listing 10 #endif /* !ACE_LACKS_PWD_FUNCTIONS */ private: ACE_HANDLE outputfd_; ACE_TCHAR programName_[256]; }; // Listing 4 code/ch10 class Slave { public: Slave () { ACE_TRACE ("Slave::Slave"); } int doWork (void) { ACE_TRACE ("Slave::doWork"); ACE_DEBUG ((LM_INFO, ACE_TEXT ("(%P) started at %T, parent is %d\n"), ACE_OS::getppid ())); this->showWho (); ACE_DEBUG ((LM_INFO, ACE_TEXT ("(%P) the private environment is %s\n"), ACE_OS::getenv ("PRIVATE_VAR"))); ACE_TCHAR str[128]; ACE_OS::sprintf (str, ACE_TEXT ("(%d) Enter your command\n"), static_cast<int>(ACE_OS::getpid ())); ACE_OS::write (ACE_STDOUT, str, ACE_OS::strlen (str)); this->readLine (str); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P) Executed: %C\n"), str)); return 0; } // Listing 4 void showWho (void) { ACE_TRACE ("Slave::showWho"); #if !defined (ACE_LACKS_PWD_FUNCTIONS) passwd *pw = ::getpwuid (ACE_OS::geteuid ()); ACE_DEBUG ((LM_INFO, ACE_TEXT ("(%P) Running this process as:%s\n"), pw->pw_name)); #endif } ACE_TCHAR* readLine (ACE_TCHAR* str) { ACE_TRACE ("Slave::readLine"); int i = 0; while (true) { ssize_t retval = ACE_OS::read (ACE_STDIN, &str[i], 1); if (retval > 0) { if (str[i] == '\n') { str[++i] = 0; return str; } i++; } else return str; } } }; // Listing 0 code/ch10 int ACE_TMAIN (int argc, ACE_TCHAR *argv[]) { if (argc > 1) // Slave mode { Slave s; return s.doWork (); } // Else, Master mode Manager m (argv[0]); return m.doWork (); } // Listing 0