C++windows核心編程筆記day13 進程、線程與訊號量,核心day13
Windows進程進程是一個容器,包含程式執行需要的代碼、資料、資源等資訊,
windows進程的特點:
每個進程都有自己的ID號
每個進程都有自己的地址空間,進程之間無法訪問對方的地址空間。
每個進程都有自己的安全屬性
每個進程至少包含一個線程。
擷取和釋放環境資訊
GetEnvironmentStrings
FreeEnvironmentStrings
擷取或設定 本程式的環境變數
GetEnvironmentVariable
SetEnvironmentVariable
樣本:
char* env=(char*) GetEnvironmentStrings();
char* env2=env;
while(env2[0])
{
printf("%s\n",env2);
env2=env2+strlen(env2)+1;
}
FreeEnvironmentStrings(env);
SetEnvironmentVariable("abc","100");
char buf[10]={0};
GetEnvironmentVariable("abc",buf,256);
printf("%s\n",buf);
進程資訊
1、進程ID
DWORD pid= GetCurrentProcessId();
2、進程控制代碼
HANDLE hpro=GetCurrentProcess();
3、啟動進程
BOOL CreateProcess(
LPCTSTR lpApplicationName,//應用程式名稱
LPTSTR lpCommandLine,//命令列參數
LPSECURITY_ATTRIBUTES lpProcessAttributes, // SD
LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
BOOL bInheritHandles,//能否被子進程使用
DWORD dwCreationFlags,//建立方式
LPVOID lpEnvironment,//環境資訊
LPCTSTR lpCurrentDirectory,//目前的目錄
LPSTARTUPINFO lpStartupInfo,//返回的:起始資訊
LPPROCESS_INFORMATION lpProcessInformation //返回的:進程資訊
);
樣本:
STARTUPINFO stinfo={0};
PROCESS_INFORMATION pi={0};
CreateProcess("C:/Windows/System32/calc.exe",0,NULL,NULL,TRUE,0,NULL,NULL,
&stinfo,&pi);
WaitForSingleObject(pi.hProcess,INFINITE);//等待訊號(一般是進程結束才有訊號)
printf("Processid=%d,handle=%d\n",pi.dwProcessId,pi.hProcess);
退出本進程
VOID ExitProcess( UINT uExitCode//退出碼
);
退出任意進程
BOOL TerminateProcess( HANDLE hProcess, // handle to the process
UINT uExitCode // exit code for the process
);
通過進程ID擷取進程控制代碼
HANDLE OpenProcess(
DWORD dwDesiredAccess, // access flag
BOOL bInheritHandle,// handle inheritance option
DWORD dwProcessId// process identifier
);
擷取和關閉進程樣本(進程ID為32):
HANDLE calc=OpenProcess(PROCESS_ALL_ACCESS,FALSE,32);
TerminateProcess(calc,-1);
進程間的等候,等候 進程/線程 訊號到來
(一般是進程結束才有訊號)
DWORD WaitForSingleObject(
HANDLE hHandle, // handle to object
DWORD dwMilliseconds // time-out interval
);
windows線程windows線程是可以執行的代碼執行個體。系統是以線程為單位發送器。
windows線程特點:
線程都有Id
線程具有自己的安全屬性
線程有什麼的記憶體棧
線程都有自己的寄存器資訊
進程多任務:每個進程都使用私人的地址空間。
線程多任務:進程內多個線程使用同一個地址空間。
線程處理函數:
DWORD WINAPI ThreadProc(
LPVOID lpParameter // thread data
);
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,// SD
SIZE_T dwStackSize, // 線程棧大小(預設1M)
LPTHREAD_START_ROUTINE lpStartAddress, // 線程處理函數
LPVOID lpParameter, //傳給線程處理函數的參數
DWORD dwCreationFlags, // creation option
LPDWORD lpThreadId //返回值:線程ID
);
dwCreationFlags:
0-建立之後立即執行
CREATE_SUSPENDED-建立之後掛起,不立即執行
//結束線程,與結束進程用法一樣
TerminateThread(...)
ExitThread(...);
CloseHandle()//關閉線程控制代碼,不是結束線程
可用WaitForSingleObject()等候線程結束
掛起線程
DWORD SuspendThread( HANDLE hThread // handle to thread);
恢複線程
DWORD ResumeThread( HANDLE hThread // handle to thread);
樣本:
DWORD CALLBACK TestProc1(LPVOID param)
{
char*txt=(char*)param;
while(1)
{
printf("%s\n",txt);
Sleep(1000);
}
}
DWORD CALLBACK TestProc2(LPVOID param)
{
char*txt=(char*)param;
while(1)
{
printf("%s\n",txt);
Sleep(1000);
}
}
void Thread()
{
DWORD tid=0;
char *txt="*************************";
HANDLE hthread1=CreateThread(NULL,0,TestProc1,txt,
0,&tid);
char *txt2="————————————";
HANDLE hthread2=CreateThread(NULL,0,TestProc2,txt2,
CREATE_SUSPENDED,&tid);
getchar();
SuspendThread(hthread1);//掛起
ResumeThread(hthread2);//恢複
}
擷取線程ID和控制代碼,與進程操作類似:
GetCurrentThreadId
GetCurrentThread
OpenThread
進程範例程式碼:
// WinEnv.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include<STDIO.H>#include<WINDOWS.H>void winProc(){char* env=(char*) GetEnvironmentStrings();char* env2=env;while(env2[0]){printf("%s\n",env2);env2=env2+strlen(env2)+1;}FreeEnvironmentStrings(env);SetEnvironmentVariable("abc","100");char buf[10]={0};GetEnvironmentVariable("abc",buf,256);printf("%s\n",buf);DWORD pid= GetCurrentProcessId();HANDLE hpro=GetCurrentProcess();}void CreateProc(){STARTUPINFO stinfo={0};PROCESS_INFORMATION pi={0};CreateProcess("C:/Windows/System32/calc.exe",0,NULL,NULL,TRUE,0,NULL,NULL,&stinfo,&pi);WaitForSingleObject(pi.hProcess,INFINITE);//等待訊號(一般是進程結束才有訊號)printf("Processid=%d,handle=%d\n",pi.dwProcessId,pi.hProcess);}void KillProc(){HANDLE calc=OpenProcess(PROCESS_ALL_ACCESS,FALSE,32);TerminateProcess(calc,-1);}int main(int argc, char* argv[]){//winProc();CreateProc();//KillProc();return 0;}
線程與訊號量使用樣本(訊號量是一種線程同步技術):
// winThread.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include<stdio.h>#include<windows.h>char g_txt[256];char g_txt2[256];CRITICAL_SECTION cs={0};HANDLE g_hSem=0;DWORD CALLBACK PrintProc(LPVOID param){char buf[10]={0};while(1){WaitForSingleObject(g_hSem,INFINITE);//有訊號才執行ZeroMemory(buf,sizeof(buf));GetEnvironmentVariable("exit",buf,sizeof(buf));if(strcmp(buf,"1")==0) break;printf("**************************\n");}return 0;}/*DWORD CALLBACK CtrlProc(LPVOID param){int i=0;while(1){SetEvent(g_hevent);//發一個訊號Sleep(1000);i++;if(i==1000) break;}return 0;}*/void Thread(){DWORD tid=0;char *txt="**************************";HANDLE hthread1=CreateThread(NULL,0,PrintProc,txt,0,&tid);/*//char *txt2="—————————————";//HANDLE hthread2=CreateThread(NULL,0,CtrlProc,txt2,//0,&tid);//HANDLE ht[2]={0};//ht[0]=hthread1;//ht[1]=hthread2;//WaitForMultipleObjects(2,ht,TRUE,INFINITE);*/SetEnvironmentVariable("exit","0");while(1){char c=getchar();if(c=='\0'||c=='\n') continue;int count=c-'0';printf("count1=%d \n",count);if(count>=0&& count<=9){printf("count2=%d \n",count);ReleaseSemaphore(g_hSem,count,NULL);//重新設定成5次}else if(c=='e'|| c=='E'){SetEnvironmentVariable("exit","1");ReleaseSemaphore(g_hSem,1,NULL);//重新設定成5次break;}}WaitForSingleObject(hthread1,INFINITE);printf("wait over!\n");CloseHandle(hthread1);//CloseHandle(hthread2);}int main(int argc, char* argv[]){g_hSem=CreateSemaphore(NULL,3,10,"s1");Thread();CloseHandle(g_hSem);return 0;}
linux下 進程訊號量與線程訊號量的不同與聯絡是什
訊號量在進程是以有名訊號量進行通訊的,線上程是以無名訊號進行通訊的,因為線程linux還沒有實現進程間的通訊,所以在sem_init的第二個參數要為0,而且在多線程間的同步是可以通過有名訊號量也可通過無名訊號,但是一般情況線程的同步是無名訊號量,無名訊號量使用簡單,而且sem_t儲存在進程空間中,有名訊號量必須LINUX核心管理,由核心結構struct ipc_ids 儲存,是隨核心持續的,系統關閉,訊號量則刪除,當然也可以顯示刪除,通過系統調用刪除,
訊息佇列,訊號量,記憶體共用,這幾個都是一樣的原理。,只不過訊號量分為有名與無名
Windows核心(驅動)編程中的線程問題
可以使用函數PsCreateSystemThread,用起來和ring3差不多,ring0編程更要注意線程同步問題,否則很容易BSOD(藍色當機畫面)