Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
EKZ.docx
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
289.38 Кб
Скачать

11)Функции создания процесса (p2-1.Cc). Затраты на порождение и переключение процесса (p5.Cc).

Рассмотрим временные затраты на создание процесса с помощью функции fork() на примере программы p2-1.cc [17]:

//p2-1.cc

#include <stdlib.h>

#include <stdio.h>

#include <inttypes.h>

#include <iostream.h>

#include <sys/neutrino.h>

#include <process.h>

#include <sys/syspage.h>

static double cycle2milisec ( uint64_t ccl ) {

const static double s2m = 1.E+3;

const static uint64_t cps = SYSPAGE_ENTRY( qtime )->cycles_per_sec;

// частота процессора:

return (double)ccl * s2m / (double)cps;

};

struct mbyte {

#pragma pack( 1 )

uint8_t data[ 1024 * 1024 ];

#pragma pack( 4 )

};

int main( int argc, char *argv[] ) {

mbyte *blk = NULL;

if( argc > 1 && atoi( argv[ 1 ] ) > 0 ) {

blk = new mbyte[ atoi( argv[ 1 ] ) ];

};

uint64_t t = ClockCycles();

pid_t pid = fork();

if( pid == -1 ) { perror( "fork" ); exit( EXIT_FAILURE );}

if( pid == 0 ) exit( EXIT_SUCCESS );

if( pid > 0 ) {

waitpid( pid, NULL, WEXITED );

t = ClockCycles() - t;

};

if( blk != NULL ) delete blk;

cout << "Fork time: " << cycle2milisec( t ) << " msec. [" << t << " cycles]" << endl;

exit( EXIT_SUCCESS );

};

Программа начинается с точки входа – функции main(). Предварительно задается структура mbyte, в которой задается блок данных размером один мегабайт. В главном потоке проверяется условие (argc > 1 && atoi( argv[ 1 ]) > 0 ), где функция atoi() преобразует символьную сстроку соответствующую первому параметру из командной строки в целое число ( argv[ 0 ] соответствует имени программы – p2-1). Если это значение больше нуля, то с помощью функции new() и структуры mbyte создается блок данных соответствующего размера. Затем с помощью функции ClockCycles() определяется в переменной t имеющей тип данных uint64_t текущее количество процессорных циклов, котрое необходимо для определения времни затрачиваемого на создание процесса.

Функция fork() создает дочерний процесс. Для дочернего процесса pid = 0 поэтому условие выполняется и дочерний процесс сразу же после проверки условия завершается функцией exit( EXIT_SUCCESS ). В это время родительский процесс ожидает завершения дочерненого порцесса на функции waitpid( pid, NULL, WEXITED ). Как только дочерний процесс завершится в переменной t = ClockCycles() - t определяется количество процессорных затраченных на порожденние процесса. Затем удаляется блок данных blk и осуществляется вывод на экран через поток вывода cout и с помощью функции cycle2milisec( t ), преобразующей процессорные циклы в секунды, время на создание и уничтожение процесса.

Интересны не только затраты на порождение нового процесса, но и то, насколько «эффективно» сосуществуют параллельные процессы в ОС, насколько быстро происходит переключение контекста с одного процесса на другой [17]. Для оценки этих затрат рассмотрим приложение р5.сс.

// P5.cc

#include <stdlib.h>

#include <inttypes.h>

#include <iostream.h>

#include <unistd.h>

#include <sched.h>

#include <sys/neutrino.h>

int main( int argc, char *argv[] ) {

unsigned long N = 1000;

if( argc > 1 && atoi( argv[ 1 ] ) > 0 ) N = atoi( argv[ 1 ] );

pid_t pid = fork();

if( pid == -1 ) cout << "fork error" << endl, exit( EXIT_FAILURE );

uint64_t t = ClockCycles();

for( unsigned long i = 0; i < N; i++ ) sched_yield();

t = ClockCycles() - t;

delay( 200 );

cout << pid << "\t: cycles - " << t << "; on sched - " << ( t / N ) / 2 << endl;

exit( EXIT_SUCCESS );

};

Программа начинается с точки входа – функции main(). Если при запуске программы в командной строке задано количество повторений цикла, то с помощью функци atoi() оно преобразуется в новое значение переменной N . Функция fork() создает дочерний процесс. И в дочернем и в родительском процессах (их главных потоках) определяются переменные t (своих для каждого процесса). Они имеют тип данных uint64_t и хранят текущее количество процессорных циклов, котрое необходимо для определения времни затрачиваемого на переключение контекста процессов.

В каждом из процессов (главных потоках) запускается N раз for-цикл, где выполняется единственная функция sched_yield(). Она переводит вызвавший ее процесс (главный поток) из состояния выполнения в состяние готовности к выполнению (хотя квант времени выделенный для работы этого потока еще не истек) и запускает передиспетчеризацию потоков.

После завершения цила каждый процесс (главный поток) определяет в своей переменной t = ClockCycles() - t количество процессорных циклов затраченных на выполнение. Делает задержку на 0,2 секунды и выводит на экран через поток вывода cout результаты своей работы. На рис.47 показано выполнение программы p5.cc в перспективе System Profiler.

Таким образом, здесь использована симметричная схема, где два одновременно выполняющихся процесса настолько симметричны и идентичны, что они даже не анализируют PID после выполнения fork(), они только в максимальном темпе «перепасовывают» друг другу активность. Рис. 48 показано взаимодействие двух идентичных процессов: вся их «работа» состоит лишь в том, чтобы как можно быстрее передать управление партнеру.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]