J'ai essayé de chronométrer combien de temps il faut pour une invocation de popen
pour terminer. popen
initialise un processus qui crée ensuite un tube, forge et invoque le shell. Dans mon cas particulier, j'utilise l'appel pour lire une autre sortie de programmes stdout
. Le problème : Je m'attends à l'appel que je fais pour retourner la bonne durée d'exécution du programme (environ 15 secondes pour un programme de test). Ce que je reçois, c'est que le programme n'a pas pris le temps de finir (0,000223s). Malgré toutes les diverses fonctions que j'ai essayées, je semble incapable de chronométrer l'appel correctement.Impossible de chronométrer l'exécution de la commande dans C (popen)?
Voici un exemple reproductible de mon problème. Il est composé du programme de calendrier et un programme d'enfants que le programme de synchronisation fonctionne (l'enfant prend environ 15 secondes pour courir sur mon système):
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#ifdef __MACH__
#include <mach/clock.h>
#include <mach/mach.h>
#endif
#define MAXBUF 10
static void gettime (struct timespec *t) {
#ifdef __MACH__
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &cclock);
clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);
t->tv_sec = mts.tv_sec;
t->tv_nsec = mts.tv_nsec;
#else
clock_gettime(CLOCK_REALTIME, t);
#endif
}
int main (void) {
FILE *fp;
struct timespec tic, toc;
char *executableName = "./a.out";
char answer[MAXBUF];
gettime(&tic);
if ((fp = popen(executableName, "r")) == NULL) {
fprintf(stderr, "The file couldn't be opened.\n");
return 1;
}
gettime(&toc);
fgets(answer, MAXBUF, fp);
double elapsed = (double)(toc.tv_nsec - tic.tv_nsec)/1E9;
fprintf(stdout, "The program says %s, and took %fs to run!\n", answer, elapsed);
pclose(fp);
return 0;
}
Voici le programme des enfants:
#include <stdio.h>
#include <stdlib.h>
int timeWastingFunction (long long n) {
if ((n % 2) == 0) {
return 1;
}
for (int i = 1; i < (n/2); i += 2) {
if ((n % i) == 0) {
return 1;
}
}
return 0;
}
int main (void) {
int start = 687217000;
while (start--) {
timeWastingFunction(start);
}
fprintf(stdout, "Hello!");
return 0;
}
Cette peut sembler un peu exagéré, mais j'avais précédemment essayé d'utiliser clock_t
, (une fonction de synchronisation basée sur CPU) pour faire le chronométrage, et obtenu les mêmes réponses. J'ai donc essayé la solution this que vous voyez ci-dessus. J'ai choisi: CLOCK_REALTIME
comme il semblait approprié pour le travail. Je n'ai malheureusement pas l'option de spécifier si cette horloge est au niveau d'un processus ou d'un thread par thread (je souhaite que ce processus soit indépendant du processus).
Note: Je n'ai pas essayé d'utiliser gettimeofday
encore, mais je ne veux pas depuis son apparence inappropriée pour chronométrer cette façon, en fonction de la date du système en utilisant, et étant éliminé en faveur de clock_gettime
.
Edit: Pour être clair, ce qui se passe quand je lance est que le programme appelant popen
sera effectivement décrochage pour les 15 secondes, l'autre programme prend pour exécuter, avant d'imprimer le temps « mauvais ». Il n'imprime pas immédiatement le temps ce qui implique qu'il n'a pas attendu l'appel pour terminer.
Votre utilisation de 'clock_gettime' est correcte [et préféré à 'gettimeofday']. Votre problème est que 'popen' renvoie [presque] immédiatement. Il n'attend pas que le processus cible se termine. Essayez: 'gettime (&tic); popen(); ...; pclose(); gettime (&toc);' –
@CraigEstey Merci! Si je veux utiliser le fichier que j'ai ouvert, cela nécessite que je ré-ouvre (exécuter dans ce cas – Micrified
Notez que macOS Sierra (10.12.x) supporte en fait 'clock_gettime()' maintenant, mais si vous ne le faites pas, vous pouvez l'utiliser sans le temps de réouverture. vous compilez du code sur Sierra pour l'exécuter sur des systèmes plus anciens, vous ne pouvez pas l'utiliser encore (et il n'est pas disponible si vous compilez sur des versions antérieures de Mac OS X donc le transfert vers Sierra ne peut pas (facilement) l'utiliser –