У меня есть родительский процесс, и я хотел бы запустить дочерний процесс на определенную продолжительность (например, N миллисекунды). Я делаю это в c++ (и в окнах).
Могу ли я предоставить некоторый параметр CreateProcess, который убьет его через некоторое время и вернет управление родительскому приложению? Если нет, есть ли другой способ сделать это?
Могу ли я предоставить некоторый параметр CreateProcess...?
Да, вы можете передать желаемую duration
(N) с параметром lpCommandLine в процесс, который нужно запустить.
Детский процесс может анализировать lpCommandLine и настраивать таймер с требуемой duration
. Этот таймер может быть, например, Waiting Timer или просто потоком с
Sleep(duration); // waits the duration
ExitProcess(GetLastError()); // exits the "remote" process
Нить (поток внутри дочернего процесса) завершает весь дочерний процесс после duration
. Идея WaitableTimer требует частого вызова функции ожидания. Подробнее см. Использование объектов ожидающего таймера.
Но: родительский процесс будет постоянно "контролироваться". Однако: вы можете дополнительно ввести состояние ожидания в родительском процессе, используя функцию ожидания (например, WaitForSingleObject, ожидая, когда дочерний процесс обработает дескриптор, чтобы фактически спящий режим родительского процесса до тех пор, пока дочерний процесс не завершится. В верхней части вы можете оценить возвращаемое значение дочерний процесс вызовом функции GetExitCodeProcess.
Описанные схемы гарантируют, что желаемая duration
лучше всего выполняется, однако вы также можете контролировать duration
от родительского процесса с помощью именованного события. Подробнее см. Использование объектов событий. При таком подходе родительский процесс может установить событие, когда duration
"потребляется". Детский процесс ждет этого события и завершается, когда событие было установлено. Этот подход может быть немного менее точным, так как родитель не совсем знает, когда началась детская duration
.
Пример с ожидаемым таймером:
Родительский процесс:
...
#define CHILD_DURATION 2000 // 2000 ms
HANDLE hProcess;
char ChildName[MAX_PATH];
char CommandLine[MAX_PATH];
sprintf_s(ChildName,MAX_PATH,"MyChild.exe");
sprintf_s(CommandLine,MAX_PATH,"%d",CHILD_DURATION);
// start the child
hProcess = CreateProcess(ChildProcessName,CommandLine,....
if (0 == hProcess)
{
// error with process creation
printf("CreateProcessfailed (%d)\n", GetLastError());
return GetLastError();
}
// and wait for it to finish
if (WAIT_OBJECT_0 == WaitForSingleObject(hProcess,INFINITE)
{
// child finished
} else
{
// error with wait
printf("WaitForSingleObject failed (%d)\n", GetLastError());
return GetLastError();
}
...
Детский процесс:
int main(int argc, char * argv[])
{
HANDLE hWaitableTimer CreateWaitableTimer(NULL,TRUE,NULL);
if (NULL == hWaitableTimer)
{
printf("CreateWaitableTimer failed (%d)\n", GetLastError());
return GetLastError();
}
DWORD dwDuration = atoi(argv[1]);
LARGE_INTEGER liDueTime = -10000 * dwDuration;
// waitable timer due time is in 100 nano second units
// negative values indicate relative time
if (!SetWaitableTimer(hTimer, &liDueTime, 0, NULL, NULL, 0))
{
printf("SetWaitableTimer failed (%d)\n", GetLastError());
return GetLastError();
}
DWORD dwKeepGoing = TRUE;
// enter the "to do" loop while waiting for the timer...
While (dwKeepGoing)
{
switch (WaitForSingleObject(hTimer,0)
{
case WAIT_OBJECT_0:
// duration over,
// optionally finalize "to do" stuff here
// and end child
dwKeepGoing = FALSE;
case WAIT_TIMEOUT:
// do stuff here
break;
case WAIT_FAILED:
// the wait function has failed
printf("WaitForSingleObject failed (%d)\n", GetLastError());
return GetLastError();
}
}
return 0;
}
Никто не убьет процесс для вас, если вы не сделаете это самостоятельно (например, из родительского процесса), или этот процесс не выйдет.
Обратите внимание, что также нет такой вещи, как "и контроль возврата к родительскому приложению". После запуска дочернего процесса как родительский, так и дочерний процессы имеют свой собственный "контроль" и выполняются одновременно, потребляя процессорное время, отдаваемое процессам операционной системой.
В общем, вы решаете, кто закончит этот процесс. Если вы делаете это из родительского процесса, то после этого вы начинаете обрабатывать дескриптор обработки и использовать (но не очень хорошо) API TerminateProcess
для дочернего процесса.
В противном случае, и это лучше, сам дочерний процесс продолжает смотреть во время выполнения и просто выходит, когда придет время:
main() {
time_to_exit = now() + N;
while(now() < time_to_exit) {
keep_doing_my_stuff();
}
}