// құрылатын ағымға берілетін ақпараттар
typedef struct _Data {
TCHAR cmd[20];
int parentThreadID;
} TDATA, *PTDATA;
DWORD WINAPI ThreadProc(LPVOID lpParam);
void ErrorReport(LPTSTRlpszFunction);
int main()
{
PTDATA pData;
DWORD dwThreadId;
HANDLE hThread;
// құрылатын ағымға берілетін ақпараттар жадын
белгілейміз
pData = (PTDATA)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, sizeof(TDATA));
239
NULL,
0,
if(pData == NULL)
{
ErrorReport(TEXT("HeapAlloc()"));
return(1);
}
// ақпараттар құрылымын толтырамыз: шығаратын команда
// айнымалы шеңберлер және қазіргі ағымның
идентификаторы
// ағымда
_tcscpy(pData->cmd, TEXT("cmd /c set ComSpec"));
pData->parentThreadID = GetCurrentThreadId();
// жаңа ағым құрамыз
hThread = CreateThread(
// әдеттегідей қауіпсіздік атрибуттары
// әдеттегідей ағым қамшысының өлшемі
ThreadProc,// pData ағымының негізгі функциялары,
//ағымға арналған ақпарат
// әдеттегідей ағым құрудың жалауы
&dwThreadId); // идентификаторын құрайды
// құрылған ағымның
// ағымның сәтті құрылғанын тексереміз
if (hThread == NULL)
{
ErrorReport(TEXT("CreateThread()"));
return(1);
}
// тайм-аутсыз ағымның аяқталуын күтеміз
WaitForSingleObject(hThread, INFINITE);
// CloseHandle(hThread) ағымының дескрипторын
жабамыз;
return(0);
}
// DWORD WINAPI ThreadProc(LPVOID lpParam)құрылатын
ағымның басты функциясы
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
PTDATA pData;
// pData = (PTDATA)lpParam құрылатын ағымына
жіберілетін ақпаратты аламыз;
// аталық-процесс туралы ақпараттың консолын аламыз
240
// туындайтын процесс туралы ақпараттың консолын
аламыз
// құрылған ағым
_tprintf (TEXT("New thread is created by thread with
Id %d and command to execute is \"%s\"\n"),
pData->parentThreadID, pData->cmd);
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// процесс-тобын қосамыз
if(!CreateProcess(NULL,// бірінші параметрді аламыз
//
pData->cmd,
// Командалық жол
NULL,
// мұраланатын құрылатын
//процесс дескрипторы
// Дескриптор первичного
//
FALSE, // мұраланбайтын ағым,
// Процесс дескрипторы аталық
// процестен мұраланбайды
0,
//
NULL // әдеттегідей процесс құру жалауы,
NULL // аталық – процесінен
// шеңбер мұраланады
// қазіргі каталог
//аталық процестен мұраланады
&si, // бастапқы қондырғыға нұсқау
// процестер үшін
&pi) // процестен және алғашқы ағым
дескрипторын аламыз
)
{
ErrorReport(TEXT("CreateProcess()"));
return(1);
}
// процесс тобы орындалуының аяқталуын күтеміз //
тайм-аутсыз
WaitForSingleObject(pi.hProcess, INFINITE);
// процесс дескрипторын және оның алғашқы ағымын
241
жабамыз //
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
// ағым параметрлерге белгіленген жадыны босатамыз
HeapFree(GetProcessHeap(), 0, pData); return(0);
}
void ErrorReport(LPTSTR lpszFunction)
{
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)
&lpMsgBuf,
0, NULL ) ;
lpDisplayBuf
=
(LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)
lpszFunction)+40)*sizeof(TCHAR));
_stprintf((LPTSTR)lpDisplayBuf,
TEXT("%s failed with error %d: %s"), lpszFunction,
dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf,
TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}
Берілген бағдарламамен жұмыс процесінде, екі параметрді
қабылдайтын: командадан, аталық ағымның идентификаторы мен
жолдан тұратын тағы бір ағым құрылады. Өз кезегінде, құрылған ағым,
өзіне берілген команданы (қарау командасының мысалында,
айнымалы шеңбердің мәндері ComSpec — «cmd /c set ComSpec»)
қолдана отырып, жаңа процесс туындатады.
Жоғарыда келтірілген бағдарлама жұмысының нәтижесінде
консолға хабарлама шығады:
242
C:\>ProcessAndThread.exe
New thread is created by thread with Id 3136 and
command to execute is "cmd /c set ComSpec"
ComSpec=C:\WIN\system32\cmd.exe
C:\>
Берілген мысалда қарастырылған, тағы бір функция қатарын еске
салған жөн. Алдымен, ол WaitForSingleObjectQ функциясы:
include
DWORD WINAPI WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds);
Бұл функция қазіргі процесте жіберілген hHandle дескрипторына
ұқсатылған обьект, сигналды күйге енбегенше немесе берілген
dwMilliseconds күту кезеңі милисекундта өтуіне дейін блоктайды. Егер
dwMilli- seconds параметрі INFINITE мәніне ие болса, онда күту кезеңі
өтіп кетпейді және процесс, берілген обьектінің сигналды күйге өтуі
кезінде оянады. WaitForObjects() тобының функциялары, Windows
тобының операциялық жүйелерімен сүйемелденетін синхрондауші
механизмдер элементінің бірі болып табылады.
Берілген функцияның күйлерін бақылай алатын обьектілер ретінде,
оқиғалар, мьютекстер, процесстер, семафорлар, ағымдар және т.б.
қатыса алады. Егер обьектілер, процестер немесе ағымдар
бақыланатын болса, онда олар үшін сигналды күй олардың
аяқталғанында түседі.
Егер функция, бақыланатын обьектілердің сигналды күйге өтуі
кезінде аяқталса, онда WAIT_ OBJECT_0 мәні қайтарылады. Егер де
функция күту кезеңінің өтуімен аяқталса, онда WAIT_TIMEOUT мәні
қайтарылады.
Егер бір уақытта бірнеше обьектілерді бақылау қажет болса, онда
WaitForMultipleObjectsQ функциясы қолданылады.
DWORD WINAPI WaitForMultipleObjects(
DWORD nCount,
const HANDLE* lpHandles,
BOOL bWaitAll,
DWORD dwMilliseconds);
243
Бұл функцияда nCount параметрі, обьектілер дескрипторы жалпы
санын анықтайды. LpHandles параметрінде обьектілер дескрипто-
рының алабы беріледі, олардың күйі WaitForMultipleObjects()
функциясымен бақыланады. Егер bWaitAll параметрі үшін TRUE мәні
қондырылса, онда функция күтілу процесін басқаруды, алаптағы
барлық обьектілерді сигналды күйге ауыстыруға ауыстырғаннан кейін
қайтарады. Қарсы жағдайда, функция барлығын бір уақытта емес бір
обьектінің сигналды күйге ауысуын күтеді. DwMilliseconds параметрі,
WaitForSingleObject() функциясы сияқты, обьектілерді сигналды күйге
ауыстыруының күтілуі кезеңін беру үшін оның бітуінен, басқару
процессі функциясының шақыртылуымен қайтарылады. Бұл жағдай,
егерде күтілу кезеңі біткенде және обьектінің бірі де сигналдық күйге
ауыспаса да жүреді. Бұл параметр сондай-ақ INFINITE мәнін қабылдай
алады.
Жұмыс аяқталғаннан соң, бұл функция, егер обьектілердің
сигналды күйге ауысуы күтілуінің уақыты өтсе, WAIT_TIMEOUT
мәнін қайтарады. Егер функцияларды шақырту кезінде bWaitAll
параметрі TRUE тең болса және барлық обьектілер күту кезеңінің
өтуіне дейін ауыстырылу керек болса, функция WAIT_OBJECT_0
мәнін қайтарады. Егер де bWaitAll параметрі FALSE тең болса және
қандай да бір обьект сигналды күйүге ауыстырылса, WAIT_OBJECT_0
+ n мәні қайтарылады, мұнда n —сигналды күйге ауыстырылған,
lpHandles алабындағы обьектінің нөмірі.
Дескрипторлары ашылатын, обьектілермен жұмысты аяқтаған соң,
соңғылары жабылуы керек. Ол үшін CloseHandle() функциясы
қолданылады:
include
DWORD WINAPI BOOL CloseHandle(HANDLE hObject);
Параметр ретінде ертерек ашылған дескриптор беріледі. Процестің
дескрипторлары және ағымдар, егер процестің өздері де, ағымдар да
аяқталған соң ғана жабылуы тиіс.
Достарыңызбен бөлісу: