* Вот как такая программа выглядела бы в Windows: (проверено в VC6)
- Код: Выделить всё
#include <stdio.h>
#include <process.h>
#include <windows.h>
const char* name = "settime";
int main (int argc, char *argv[]) {
char* end; unsigned count; int status;
int pid; // на самом деле хендл
if (argc <3 || (count = strtoul(argv[1], &end, 10), *end)) {
printf("Usage: %s count command parameters...\n", name); return 1;
}
if ((pid =_spawnvp(_P_NOWAIT, argv[2], argv+2)) <0) {
printf("%s: cannon spawn %s\n", name, argv[2]);
return -1;
}
if (WaitForSingleObject(pid, count*1000) == WAIT_TIMEOUT)
TerminateProcess(pid, 0);
GetExitCodeProcess(pid, &status);
return status;
}
Ничего хитрого: последовательный вызов _spawnvp, WaitForSingleObject и TerminateProcess либо GetExitCodeProcess. (На чистом WinAPI вышло бы лишь чуть-чуть сложнее, за счёт самостоятельного сбора-разбора командной строки.)
* Но вот во FreeBSD сразу же начинаются проблемы из-за вынесенных в заголовок дырявых интерфейсов системных библиотек. (Когда маны пестрят фразами типа "этой функции совсем не место в этой библиотеке, но все уже привыкли", как про kvm_getprocs(3), -- это явный признак проекта, пущенного на самотёк.)
Прежде всего, FreeBSD предоставляет три способа запустить новый процесс: fork(2) со товарищи, system(3) и popen(3). (Вопрос №2: я ничего не забыл?) Про fork я уже писал: она создаёт копию текущего процесса, и возвращает родителю PID ребёнка, а ребёнку -- 0, после чего они продолжают выполняться с одного места. system создаёт ребёнка, ждёт его завершения, и возвращает код его возврата, а popen создаёт ребёнка со входом и/или выходом, перенаправленным в трубу, и возвращает хэндл этой трубы.
Предоставляемой в VC функцией spawn, и по-моему, совершенно естественной возможности запустить ребёнка, и, не дожидаясь его завершения, получить его PID -- в стандартных библиотеках нет. Неужели это настолько необычная задача, что для её решения нужна конструкция switch(pid=fork()) {case -1: /* неудача */ case 0: exec(...); } /* теперь pid заполнен */ (Это вопрос №3)
Следующая оплеуха от FreeBSD -- полное отсутствие функций ожидания с таймаутом. Чтобы его реализовать, надо заводить будильник (alarm(3)) на нужное время, и по его сигналу каким-то образом ожидание прерывать. Будильник один на весь процесс, поэтому если им попользовалась какая-то из системных функций (например, sleep(3)) -- он сбрасывается. Вопрос №4: почему на то, что в Windows реализуется одним вызовом WaitForSingleObject, во FreeBSD нужно тратить полстраницы среднеизощрённого кода?
* Вот что у меня в результате получилось. Оно даже работает; однако, сравните длину с версией для Windows.
- Код: Выделить всё
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <stdlib.h>
const char* name = "settime";
unsigned pid;
static void sig_handler(int sig) {
kill(pid, SIGTERM);
}
int main (int argc, char *argv[]) {
char* end; unsigned count; int status;
if (argc <3 || (count = strtoul(argv[1], &end, 10), *end)) {
printf("Usage: %s count command parameters...\n", name); return 1;
}
switch (pid =fork()) {
case -1:
printf("%s: cannot fork\n", name);
return -1;
case 0:
execvp(argv[2], argv+2);
printf("%s: cannon exec %s\n", name, argv[2]);
return -2;
}
signal(SIGALRM, sig_handler);
alarm(count);
waitpid(pid, &status, 0);
return status;
}
Если такая программа вам нужна под одной из двух представленных ОС, можете пользоваться