Я занимаюсь разработкой тестового ПО, для тестирования железа. И у меня стоит задача запускать тестирующие программы параллельно друг другу. И не просто запускать, а ещё и обрабатывать их вывод и результаты теста.
Делаю это следующем образом: запускаю отдельно тестирующий поток, а уже в нём с помощью popen запускаю тестируемый поток. Проблема заключается в том, что процессы выполняются последовательно, не смотря на многопоточность. Поясню примером кода. Проверка на ошибки опущена.
static id=0; //счётчик запущенных процессов
int runner(void * ini_file_data_st_ptr, LPVOID sys_hwd_ptr)
{
....
int result;
pthread_t th_usbtest, th_ledtest, th_comtest, th_framtest, th_hddtest;
// test USB
if (ifd ->usbCount>0) { //если у нас есть тестирование USB
id++; //увеличиваем счётчик
result = pthread_create(&th_usbtest, NULL, usbtest, &id); //запускаем поток "usbtest"
printf("Creating the usbtest thread\n");
}
//test LED
if (ifd ->ledsFlag) {
id++;
result = pthread_create(&th_ledtest, NULL, ledtest, &id); //запускаем поток "ledtest"
}
//test COM
if (ifd ->comCount>0) {
id++;
result = pthread_create(&th_comtest, NULL, comtest, &id); //запускаем поток "comtest"
}
//... и так далее остальные процессы
while (id!=0) { //костыли для ожидания окончания работы процессов, чтобы не возиться с мьютексами и семафорами
sleep(1);
}
}
Все функции процессов (usbtest, ledtest, comtest и т.д.) примерно одинаковые. Поэтому я приведу пример одной из них.
#define USB_TEST_PATH "./usbtest"
void *usbtest (void *arg){
FILE* f;
ptrSysHWD->usbCount=0; //технические данные
gl_tst_result.usb=true;
char buf[128];
char path[128];
sprintf(path,"%s %d", USB_TEST_PATH, ifd ->usbCount); //формируем команду запуска программы с параметрами (передаём количество юсб)
f = popen(path,"r"); //запускаем программу
while (fgets(buf,127,f)) //читаем всё то что программа выводит
{
// ********************* !!!
printf("%s\n",buf); //выводим на экран
fflush(stdout); // ФЛУШИМ!!!
// ********************* !!!
if ((strstr(buf, "error") != NULL) || (strstr(buf, "not found") != NULL ) || (strstr(buf, "Error") != NULL) || (strstr(buf, "failed") != NULL)) {
printf ("USB HARDWARE ERROR\n");
gl_tst_result.usb=false;
} //проверяем на ошибки
if (strstr(buf, " OK!") != NULL) { //считаем количество устройств
ptrSysHWD->usbCount++;
}
}
fclose(f); //после того, как прочитали закрываем программу
id--; //минусуем счётчик потока
}
Остальные потоки аналогичные, запускают другие аппаратные тесты. Фишка в том, что некоторые тесты могут выполняться по несколько десятков секунд. И вот парадокс, что несмотря на fflush(stdout); у меня в логах идёт последовательный вывод всех программ. Т.е. я понимаю так, что если потоки работают параллельно и дескрипторы открытых файлов стандартного вывода одинаковые, то у них должен быть перекрещивающийся вывод. А этого нет.
Из чего можно заключить: потоки и программы выполняются
ПОСЛЕДОВАТЕЛЬНО! Хотя запуск каждого потока идёт параллельно. Что я делаю не так? И как это исправить?