Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Метода Процессы и потоки.doc
Скачиваний:
7
Добавлен:
14.07.2019
Размер:
401.92 Кб
Скачать

Процессы, нити и волокна

В Windows NT/2000 и Windows 9.x поддерживаются мультинитевые процессы. Про­цесс (process) представляет собой объект, которому принадлежат ресурсы приложения. А нить (thread) – это независимый путь выполнения внутри процесса, разделяющий вместе с процессом общее адресное пространство, код и глобальные данные. У каждой нити имеются собственные регистры, стек и механизмы ввода, в том числе и очередь скрытых сообщений. В Windows NT/2000 и Windows 9.x временные интервалы выделя­ются на основе нитей, а вытесняющая многозадачность реализуется на базе приорите­тов, назначаемых для каждой нити. Кроме того, в Windows NT/2000 имеется возмож­ность использовать несколько процессоров для обслуживания нитей процесса. Чем больше процессоров, тем больше временных интервалов имеется для нитей. Благода­ря такой возможности, процессы, которые выполняются на машине с двумя и более процессоров, работающей под управлением Windows NT/2000, в принципе могут выпол­няться быстрее, чем в случае, если бы они выполнялись под управлением Windows 9.x.

Создание процессов и нитей

Функция CreateProcess создает объект процесса, а также объект основной нити при­ложения. Функция CreateProcess дает также родительскому процессу возможность ус­танавливать рабочую среду для нового процесса, в том числе и новый рабочий каталог, способ отображения этого процесса на экране, его переменные окружения, приоритет и передаваемую ему командную строку. Выполнение нового процесса начнется с адреса его запуска и будет продолжено вплоть до его завершения.

Листинг 1. Применение функции CreateProcess для выполнения программы

CrProces.h

#define IDM_EXIT 100

#define IDM_TEST 200

#define IDM_ABOUT 301

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);

LRESULT CALLBACK About (HWND, UINT, WPARAM, LPARAM);

CrProces.rc

#include "windows.h"

#include "CrProces.h"

MYAPP ICON DISCARDABLE "GENERIC.ICO"

MYAPP MENU DISCARDABLE

BEGIN

POPUP "&File"

BEGIN

MENUITEM "E&xit", IDM_EXIT

END

MENUITEM "&Test!", IDM_TEST

POPUP "&Help"

BEGIN

MENUITEM "&About My Application...", IDM_ABOUT

END

END

ABOUTBOX DIALOG 22, 17, 171, 43

STYLE DS_MODALFRAME | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU

CAPTION "My Application"

FONT 8, "MS Sans Serif"

{

CONTROL "MyApp", -1, "STATIC", SS_ICON | WS_CHILD | WS_VISIBLE, 3, 2, 16, 16

CONTROL "Generic Application", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 28, 4, 100, 8

CONTROL "OK", IDOK, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 116, 26, 50, 14

}

CrProces.C

#include <windows.h>

#include "CrProces.h"

HINSTANCE hInst; // current instance

LPCTSTR lpszAppName = "MyApp";

LPCTSTR lpszTitle = "My Application";

Int apientry WinMain( hinstance hInstance, hinstance hPrevInstance,

LPTSTR lpCmdLine, int nCmdShow)

{

MSG msg;

HWND hWnd;

WNDCLASSEX wc;

// Register the main application window class.

//............................................

wc.style = CS_HREDRAW | CS_VREDRAW;

wc.lpfnWndProc = (WNDPROC)WndProc;

wc.cbClsExtra = 0;

wc.cbWndExtra = 0;

wc.hInstance = hInstance;

wc.hIcon = LoadIcon( hInstance, lpszAppName );

wc.hCursor = LoadCursor(NULL, IDC_ARROW);

wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);

wc.lpszMenuName = lpszAppName;

wc.lpszClassName = lpszAppName;

wc.cbSize = sizeof(WNDCLASSEX);

wc.hIconSm = LoadImage( hInstance, lpszAppName,

IMAGE_ICON, 16, 16,

LR_DEFAULTCOLOR );

if ( !RegisterClassEx( &wc ) )

return( FALSE );

hInst = hInstance;

// Create the main application window.

//....................................

hWnd = CreateWindow( lpszAppName,

lpszTitle,

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, 0,

CW_USEDEFAULT, 0,

NULL,

NULL,

hInstance,

NULL

);

if ( !hWnd )

return( FALSE );

ShowWindow( hWnd, nCmdShow );

UpdateWindow( hWnd );

while( GetMessage( &msg, NULL, 0, 0) )

{

TranslateMessage( &msg );

DispatchMessage( &msg );

}

return( msg.wParam );

}

HWND hList = NULL;

LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )

{

switch( uMsg )

{

case WM_CREATE :

// Create list box.

//.................

hList = CreateWindowEx( WS_EX_CLIENTEDGE, "LISTBOX", "",

LBS_STANDARD | LBS_NOINTEGRALHEIGHT |

WS_CHILD | WS_VISIBLE,

0, 0, 10, 10,

hWnd, (HMENU)101,

hInst, NULL );

break;

case WM_SIZE :

if ( wParam != SIZE_MINIMIZED )

MoveWindow( hList, 0, 0, LOWORD( lParam ), HIWORD( lParam ), TRUE );

break;

case WM_COMMAND :

switch( LOWORD( wParam ) )

{

case IDM_TEST:

{

STARTUPINFO si;

PROCESS_INFORMATION pi;

// Initialize structures.

//.......................

ZeroMemory( &si, sizeof(STARTUPINFO) );

ZeroMemory( &pi, sizeof(PROCESS_INFORMATION) );

si.cb = sizeof( STARTUPINFO );

si.dwFlags = STARTF_USESHOWWINDOW;

si.wShowWindow = SW_SHOWNORMAL;

CreateProcess( NULL, "CALC", NULL, NULL, FALSE,

0, NULL, NULL, &si, &pi );

WaitForInputIdle( GetCurrentProcess(), INFINITE );

// Loop until process terminates.

//...............................

if ( pi.hProcess )

{

DWORD dwExitCode = STILL_ACTIVE;

while ( dwExitCode == STILL_ACTIVE )

{

WaitForSingleObject( pi.hProcess, 1000 );

GetExitCodeProcess( pi.hProcess, &dwExitCode );

SendMessage( hList, LB_INSERTSTRING, 0, (LPARAM)"Waiting for Calc." );

UpdateWindow( hWnd );

}

SendMessage( hList, LB_INSERTSTRING, 0, (LPARAM)"Calc is Finished" );

}

}

break;

case IDM_ABOUT :

DialogBox( hInst, "AboutBox", hWnd, (DLGPROC)About );

break;

case IDM_EXIT :

DestroyWindow( hWnd );

break;

}

break;

case WM_DESTROY :

PostQuitMessage(0);

break;

default :

return( DefWindowProc( hWnd, uMsg, wParam, lParam ) );

}

return( 0L );

}

LRESULT CALLBACK About( HWND hDlg,

UINT message,

WPARAM wParam,

LPARAM lParam)

{

switch (message)

{

case WM_INITDIALOG:

return (TRUE);

case WM_COMMAND:

if ( LOWORD(wParam) == IDOK

|| LOWORD(wParam) == IDCANCEL)

{

EndDialog(hDlg, TRUE);

return (TRUE);

}

break;

}

return (FALSE);

}

Функция CreateThread создает новую нить внутри текущего процесса. Эта функ­ция дает процессу возможность распределить работу, выполняемую приложением, но нескольким нитям ради ускорения времени выполнения приложения. Нити, как пра­вило, используются для выполнения фоновых задач, в частности, для разбиения тек­ста на страницы, выполняемого текстовым редактором. С помощью нитей подобное разбиение на страницы происходит по мере ввода пользователем текста документа, причем пользователь не ощущает в этом случае никаких задержек.

Нити разделяют вместе с процессом общее адресное пространство и системные ресурсы. Однако у них имеется собственный стек, а в Windows NT/2000 – и собствен­ные дескрипторы защиты. Для создания нити требуется следующая информация:

* Размер стека нити

* Атрибуты защиты нити. Для указания установленной по умолчанию защиты в Windows NT/2000 либо в среде Windows 9.x, где защита не поддерживается, можно использовано значение NULL.

* Адрес процедуры, с которой начинается выполнение. Это должна быть функция, которая получает в качестве единственного параметра 32-разрядное значение.

* Дополнительное 32-разрядное значение, которое передается в процедуру нити.

* Флаги, которые, помимо прочего, допускают установку уровня приоритета нити.

* Адрес для хранения идентификатора нити. Идентификатор нити представляет со­бой уникальное системное значение.

После вызова приложением функции CreateThread для создания новой нити эта функция возвращает дескриптор нового объекта нити. Этот дескриптор использует­ся для управления нитью, а кроме того, он предоставляет вызывающему процессу возможность удаления нити, если в этом возникнет потребность. Пример создания нитей с помощью функции CreateThread приведен в описании указанной функции далее в главе.