Задание 9 параллельная обработка файлов
Программа получает через аргументы командной строки несколько имён файлов и ищет в каждом файле количество вхождений некоторого символа. В конце программа должна выводить количество вхождений. Если при работе с файлом были какие-либо ошибки (например, он не был открыт), сведения об этом должны выводиться в конце, вместе с количеством вхождений символов. Символ можно для каждого файла генерировать случайный образом, это не имеет значения.
Рекомендуется для каждого файла создать структуру со следующими полями: имя файла, символ, флаг о наличии ошибок и количество символов. Рекомендуется написать функцию, которая получает указать на эту структуру в качестве параметра и не должна использовать глобальные данные. При выполнении функция должна заполнить поля — флаг о наличии/отсутствии ошибки и количество символов. Не рекомендуется, чтобы функция выводила какие-либо сообщения на экран (по крайней мере, в окончательном варианте).
Программа должна иметь следующую структуру:
- Создание массива структур для каждого файла.
- Исполнение функции с параметром-структурой в цикле.
- Вывод данных, накопленных в структурах.
Сначала необходимо выполнить программу без использования потоков и убедиться в её работоспособности.
Затем её нужно модифицировать так, чтобы функции выполнялись в отдельных потоках. Структура программы будет следующая:
- Создание массива структур для каждого файла.
- Создание потока с функции и параметром-структурой в цикле.
- Ожидание завершения потоков.
- Вывод данных, накопленных в структурах.
Файлы нужно предварительно создать, они должны быть достаточно большими (> 10M). Следует сравнить быстродействие обоих вариантов программы.
Полезные ссылки
Полезные заголовки
#include <pthread.h>
Полезные функции
Создание нового потока:
int pthread_create( pthread_t *restrict thread, const pthread_attr_t *restrict attr, void *(*start_routine)(void *), void *restrict arg);
Прекращение выполнения потока:
void pthread_exit(void *value_ptr);
Получение идентификатора текущего потока:
pthread_t pthread_self(void);
Посылка сигнала потоку:
int pthread_kill(pthread_t thread, int sig);
Прекращение потока:
int pthread_cancel(pthread_t thread);
Приостановка текущего потока до завершения потока с идентификатором
thread
:int pthread_join(pthread_t thread, void **value_ptr);
Проверка того, что
t1
иt2
идентифицируют один и тот же поток:int pthread_equal(pthread_t t1, pthread_t t2);
Создание объекта для установки атрибутов потока:
int pthread_attr_init(pthread_attr_t *attr);
Удаление объекта для установки атрибутов потока:
int pthread_attr_destroy(pthread_attr_t *attr);
Установка размеров стека для потока:
int pthread_attr_getstacksize( const pthread_attr_t *restrict attr, size_t *restrict stacksize); int pthread_attr_setstacksize( pthread_attr_t *attr, size_t stacksize);
(и другие
pthread_attr_*
-функции.)Выполнение инициализации мьютекса:
int pthread_mutex_init( pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
Удаление мьютекса:
int pthread_mutex_destroy(pthread_mutex_t *mutex);
Наложение мюьтекса:
int pthread_mutex_lock(pthread_mutex_t *mutex);
Освобождение мьютекса:
int pthread_mutex_unlock(pthread_mutex_t *mutex);
Попытка наложения мьютекса без блокировки текущего потока:
int pthread_mutex_trylock(pthread_mutex_t *mutex);