Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабы(ОС) / Lab5 / LabOS_5.doc
Скачиваний:
57
Добавлен:
17.04.2013
Размер:
82.94 Кб
Скачать

Передача данных в поток

Т.к. тип аргумента, передаваемого в поток, - void*, то для передачи одного параметра типа int его следует преобразовать к типу (void*) (См., например, текст программы simple_threads.c в приложении.) Для передачи большего количества параметров аргумент потока должен быть указателем на структуру или область данных, содержащую передаваемые параметры.

Необходимо, чтобы данные, передаваемые новому потоку, были доступны потоку, при этом не следует передавать стековые переменные. Как Вы думаете, почему?

Задание 2. Выполните программу pr2.c. Программа создает два новых потока: один печатает 'x', другой 'o' на устройстве stderr. Каждый поток печатает определенное количество символов и затем завершается возвратом из функции потока. Оба потока используют одну и ту же функцию, char_print, но вызывают ее с разными значениями параметров.

/* pr2.c */

#include <pthread.h>

#include <stdio.h>

struct char_print_parms

{

char character; /* Символ, который печатать */

int count; /* Сколько раз печатать символ */

};

void* char_print (void* parameters)

{

/* Преобразовать указатель к нужному типу */

struct char_print_parms* p = (struct char_print_parms*) parameters;

int i;

for (i = 0; i < p->count; ++i)

fputc (p->character, stderr);

return NULL;

}

int main ()

{

pthread_t thread1_id;

pthread_t thread2_id;

struct char_print_parms thread1_args;

struct char_print_parms thread2_args;

thread1_args.character = ’x’;

thread1_args.count = 30; /* Печатать 'x' 30 раз */

pthread_create (&thread1_id, NULL, &char_print, &thread1_args);

thread2_args.character = ’o’;

thread2_args.count = 20; /* Печатать 'о' 20 раз */

pthread_create (&thread2_id, NULL, &char_print, &thread2_args);

return 0;

}

Внимание! Данная программа содержит ошибку. Для отладки программы добавьте в функцию потока печать переданных параметров. Исправьте ошибку и поясните ее причину.

Объединение потоков

В случае потоков аналогом функции wait является функция pthread_join: поток, вызвавший эту функцию, будет ожидать завершения указанного потока. Функция возвращает ноль в случае нормального выполнения, и не ноль в случае ошибки. Функция имеет два параметра: ID потока, завершения которого следует ожидать, и переменную типа указатель на void, куда будет записано значение, возвращаемое потоком. Если это значение не требуется, то второй параметр функции pthread_join может быть NULL.

Задание 3. Создайте программу pr3.c, модифицировав программу pr2.c: a) добавьте в главный поток вызов функций pthread_join для ожидания завершения обоих дочерних потоков; b) верните из дочерних потоков какие-нибудь значения (разные!) и распечатайте их в главном потоке.

II. Сравнение потоков и процессов

Изучите работу четырех программ, makefile, simple.c, simple_processes.c, simple_threads.c, simple_mutex.c, приведенных в Приложении (Тексты программ и makefile содержатся в файле appendix.doc):

  1. Обычная программа simple.c, состоящая из функции main и двух дополнительных функций; не использует многозадачности или многопоточности.

  2. Программа simple_processes.c запускает три процесса - родительский и два дочерних.

  3. Программа simple_threads.c запускает три потока - главный (первичный) и два дочерних.

  4. Программа simple_mutex.c с тремя потоками, как в (с), и использующая мьютекс для синхронизации.

Программы (a), (b) и (c) выполняют одинаковые вычисления.

Задание 4.

4.1. Скопируйте файлы makefile, simple.c, simple_processes.c, simple_threads.c, simple_mutex.c в ваш каталог. Для создания исполняемых файлов всех четырех программ запустите утилиту make без параметров.

4.2. Запустите исполняемые файлы simple, simple_processes и simple_threads. Объясните полученные результаты.

4.3. Попытайтесь оценить время выполнения программ simple, simple_processes и simple_threads. Это можно сделать одним из двух способов:

  1. Использовать в функции main всех трех программ функцию gettimeofday (не забудьте включить <sys/time.h>). Эту функцию следует включить в два места программы: до и после вызова двух функций в simple; до и после создания и запуска двух процессов/потоков в simple_processes/simple_threads. Для получения более точного результата исключите printf из функций do_one_thing и do_another_thing.

  2. Использовать обычные часы. Для того чтобы программа выполнялась несколько минут, следует включить в main каждой программы цикл, повторяющийся не менее 32000 раз. Для получения более точного результата исключите printf из функций do_one_thing и do_another_thing.

Объясните разницу во времени работы трех программ.

4.4. Выполните программу simple_mutex. Проверьте, что переменная common (изменяемая параллельно двумя потоками), изменяет свою величину от 0 до 100 (т.к. каждый поток изменяет эту переменную ровно 50 раз). Обратите внимание, что в каждый момент времени переменная common читается, увеличивается на 1 и затем записывается без прерывания только одним потоком. Это обеспечивается механизмом мьютексов, который используется обоими потоками (см. функции pthread_mutex_lock и pthread_mutex_unlock).

4.5. Затем удалите механизм мьютексов из программы simple_mutex_c, перекомпилируйте ее и выполните несколько раз. Одинаковы ли значения common в разных запусках? Всегда ли переменная common имеет конечное значение, равное 100? Объясните результаты.

4.6. Между двумя последовательными чтением и записью common, каждый из двух потоков в программе simple_mutex.c выполняет длинный цикл. Каково влияние продолжительности этого цикла на переменную common? Для ответа на этот вопрос выполните еще три эксперимента без механизма мьютексов. В первом эксперименте удалите цикл полностью. Во втором эксперименте уменьшите продолжительность цикла в два раза по сравнению с начальной версией программы. В третьем эксперименте увеличьте продолжительность цикла в два раза по сравнению с начальной версией программы. Запишите и объясните результаты экспериментов.

Соседние файлы в папке Lab5