Тебе нужно использовать системные вызовы fork и exec в юниксподобных системах и CreateProcess в винде.
Вот небольшой пример класса для асинхронной работы с порождённым дочерним процессом:
externalprocess.h
#ifndef EXTERNALPROCESS_H
#define EXTERNALPROCESS_H
#include <string>
#ifdef WIN32
// Windows nonportable headers
#include <windows.h>
#else
// Linux nonportable headers
#include <sys/types.h>
#endif
/**
*@brief Clas for run some process and handle it
*/
class ExternalProcess {
public:
/// * @brief Constructor
ExternalProcess(const std::string& command);
/// @brief Destructor
~ExternalProcess();
/// @brief Runs the process.
bool run();
/// @brief Kills the process
void kill();
/// @brief Checks that child process still exists
bool isRunning();
/// @brief reads process output
std::string readOutput() const;
private:
std::string p_command;
#ifdef WIN32
// Non portable windows part of the class interface
HANDLE p_child;
HANDLE p_stdout;
#else
// Non portable Linux part of the interface
pid_t p_pid;
int p_stdout;
#endif
};
#endif
externalprocess.unix.cpp
#include "externalprocess.h"
#include <unistd.h>
#include <cstdlib>
#include <cstdio>
#include <fcntl.h>
#include <csignal>
#include <wait.h>
#define READ_BUFSIZE 1000
/**
* @param path full path to the executable
*/
ExternalProcess::ExternalProcess(const std::string& command) {
p_command = command;
p_pid = -1;
}
/**
* It doesn't stops the processes being run. Only closes pipes.
* Use ExternalProcess::kill() If you want to kill the process.
* @sa ExternalProcess::kill()
*/
ExternalProcess::~ExternalProcess() {
close(p_stdout);
}
/**
* @return true if process started successfully otherwise returns false
*/
#define READ 0
#define WRITE 1
bool ExternalProcess::run() {
int p_out[2];
if (pipe(p_out) != 0) {
return false;
}
if ( fcntl(p_out[READ], F_SETFL, O_NONBLOCK) == -1 ) {
close(p_out[READ]);
close(p_out[WRITE]);
return false;
}
if ( fcntl(p_out[WRITE], F_SETFL, O_NONBLOCK) == -1 ) {
close(p_out[READ]);
close(p_out[WRITE]);
return false;
}
p_pid = fork();
if (p_pid < 0) {
return false;
}
else if (p_pid == 0) {
// Child process
close(p_out[READ]);
if ( p_out[WRITE] != STDOUT_FILENO ) {
if ( dup2(p_out[WRITE], STDOUT_FILENO) != STDOUT_FILENO ) {
close(p_out[WRITE]);
exit(1);
}
}
execl("/bin/sh", "sh", "-c", p_command.c_str(), NULL);
perror("execl");
close( p_out[WRITE] );
exit(1);
}
// Parent process
close(p_out[WRITE]);
p_stdout = p_out[READ];
return true;
}
void ExternalProcess::kill() {
if ( this->isRunning() ) {
::kill(p_pid,SIGKILL);
if ( waitpid(p_pid,0,0) == p_pid ) {
p_pid = -1;
} else {
// TODO Throw exception here
}
}
}
bool ExternalProcess::isRunning() {
if ( p_pid == -1 ) {
return false;
}
pid_t check = waitpid(p_pid,0,WNOHANG);
if ( check == 0 ) {
return true;
}
if ( check == p_pid ) {
p_pid = -1;
return false;
}
if ( p_pid < 0 ) {
// TODO it's better to throw exception here or log
// error before returning false.
}
return false;
}
/**
* @return new child process output since last call or empty
* string if no new output was produced.
*/
std::string ExternalProcess::readOutput() const {
char buf[READ_BUFSIZE];
int bytes_read;
std::string result = "";
while ( (bytes_read = read(p_stdout, buf , READ_BUFSIZE)) > 0 ) {
result += std::string(buf,bytes_read);
}
return result;
}
externalprocess.win.cpp
#include "externalprocess.h"
#define READ_BUFSIZE 1000
ExternalProcess::ExternalProcess(const std::string& command) {
p_command = command;
p_child = NULL;
}
ExternalProcess::~ExternalProcess() {
}
bool ExternalProcess::run() {
PROCESS_INFORMATION proc_info;
STARTUPINFO start_info;
BOOL success = FALSE;
SECURITY_ATTRIBUTES pipe_sattr;
HANDLE child_stdout_r = NULL;
HANDLE child_stdout_w = NULL;
pipe_sattr.nLength = sizeof(SECURITY_ATTRIBUTES);
pipe_sattr.bInheritHandle = TRUE;
pipe_sattr.lpSecurityDescriptor = NULL;
if ( ! CreatePipe(&child_stdout_r, &child_stdout_w, &pipe_sattr, 0) ) {
return false;
}
if ( ! SetHandleInformation(child_stdout_r, HANDLE_FLAG_INHERIT, 0) ) {
return false;
}
ZeroMemory( &proc_info, sizeof(PROCESS_INFORMATION) );
ZeroMemory( &start_info, sizeof(STARTUPINFO) );
start_info.cb = sizeof(STARTUPINFO);
start_info.hStdOutput = child_stdout_w;
start_info.dwFlags |= STARTF_USESTDHANDLES;
TCHAR* command = new TCHAR(p_command.size()+1);
strcpy(command,p_command.c_str());
success = CreateProcess(NULL,
command, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&start_info, // STARTUPINFO pointer
&proc_info); // receives PROCESS_INFORMATION
if ( ! success ) {
return false;
}
if ( !CloseHandle(child_stdout_w) ) {
this->kill();
return false;
}
p_child = proc_info.hProcess;
p_stdout = child_stdout_r;
return true;
}
void ExternalProcess::kill() {
if ( this->isRunning() ) {
if ( TerminateProcess(p_child,0) == 0 ) {
// TODO Throw exception here
return;
}
WaitForSingleObject( p_child, INFINITE ); // FIXME Is it safe to wait forever?!!!
p_child = NULL;
}
}
bool ExternalProcess::isRunning() {
if ( p_child == NULL ) {
return false;
}
DWORD exit_code = STILL_ACTIVE;
GetExitCodeProcess(p_child, &exit_code);
if ( exit_code != STILL_ACTIVE ) {
p_child = NULL;
return false;
}
return true;
}
std::string ExternalProcess::readOutput() const {
char buf[READ_BUFSIZE];
DWORD bytes_read;
DWORD aval_data_size = 0;
std::string result = "";
PeekNamedPipe(p_stdout,NULL,0,NULL,&aval_data_size,NULL);
while ( aval_data_size != 0 ) {
DWORD bytes_to_read = (aval_data_size < READ_BUFSIZE) ? aval_data_size : READ_BUFSIZE;
ReadFile(p_stdout, buf , bytes_to_read, &bytes_read, NULL);
result += std::string(buf,bytes_read);
PeekNamedPipe(p_stdout,NULL,0,NULL,&aval_data_size,NULL);
}
return result;
}
Соответственно под линухом второй файл компилировать не нужно.
Ты кажется в соседней теме про Qt спрашивал. В Qt есть готовый класс QProcess который позволяет запускать приложения и работать с ними асинхронно.