《TCP/IP網絡編程》第19章

《TCP/IP網絡編程》第19章

  • 內核對象(Kernel Objects)
    • 定義
    • 內核對象歸操作系統所有
  • Windows線程創建
    • 進程與線程
    • 創建線程
    • 創建線程安全函數
  • 內核對象的2種狀態
    • 內核對象狀態及狀態查看
    • WaitForSingleObject & WaitForMultipleObjects

內核對象(Kernel Objects) 定義

Windows操作系統創建並管理的資源(Resouce),進程、線程、文件、信號量、互斥量等。

不同資源管理方式有差異。

  • 文件管理,註冊並更新文件相關的數據I/O
    位置、文件的打開模式(read or write)等。
  • 線程管理,註冊並維護線程ID、線程所屬進程等信息。

操作系統為瞭以記錄相關信息的方式管理各種資源,在其內部生成數據塊(結構體變量,內核對象)。

內核對象歸操作系統所有

內核對象的創建、管理、銷毀時機的決定等工作均由操作系統完成。

Windows線程創建 進程與線程

非顯示創建線程的程序,單一線程模型的應用程序。
顯示創建單獨線程的程序,多線程模型的應用程序。
main函數的運行基於線程完成,進程是裝有線程的籃子,實際的運行主體是線程。

創建線程

區分內核對象的整數型句柄(HANDLE),類似於Linux的文件描述符。

#include //失敗NULLHANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,//線程安全相關信息,NULL默認SIZE_T dwStackSize,//線程棧大小,0默認大小LPTHREAD_START_ROUTINE lpStartAddress,//函數LPVOID lpParameter,//參數DWORD dwCreationFlags, //線程創建後的行為,0線程創建後立即進入可執行狀態LPDWORD lpThreadId //線程ID);

Windows線程在main函數返回時銷毀。

創建線程安全函數

#include //失敗0unitptr_t _beginthreadex( //unitptr_t,64位unsigned整型void *security,//線程安全相關信息,NULL默認unsigned stack_size,//線程棧大小,0默認大小unsigned (*start_address)(void *),//函數void *arglist,//參數unsigned initflag, //線程創建後的行為,0線程創建後立即進入可執行狀態unsigned *thrdaddr //線程ID);//_beginthread會讓創建線程時返回的句柄失效,以防止訪問內核對象

thread1_win.c

#include #include #include  //_beginthreadex, _endthreadexunsigned WINAPI ThreadFunc(void *arg);//WINAPI,Windows固有關鍵字,指定參數傳遞方向、分配的棧返回方式等函數調用相關規定。int main(int argc, char *argv[]) {HANDLE hThread;unsigned threadID;int param=5;hThread=(HANDLE)_beginthreadex(NULL, 0, ThreadFunc, (void*)&param, 0, &threadID);if(hThread==0) {puts("_beginthreadex() error");return -1;}Sleep(3000);puts("end of main");return 0;}unsigned WINAPI ThreadFunc(void *arg) {int i;int cnt=*((int*)arg);for(i=0; i<cnt; i++) {Sleep(1000);puts("running thread");}return 0;}
cl /EHsc thread1_win.c /Fe:thread1_win.exethread1_win

線程屬於操作系統管理資源,伴隨內核對象的創建,為瞭引用內核對象而返回句柄。

句柄區分內核對象,內核對象區分線程,線程句柄區分線程。

句柄的整數值在不同進程中可能重復,線程ID在跨進程范圍內不會重復。

線程ID區分操作系統創建的所有線程。

內核對象的2種狀態

應用程序實現過程中需要特別關註的信息被賦予某種“狀態”。線程終止狀態又稱signaled狀態,未終止狀態稱為non-signaled狀態。

內核對象狀態及狀態查看

進程或線程的內核對象初始狀態是non-signaled狀態,終止時是signaled狀態。

通過boolean變量表示,初始值為FALSE(non-signaled狀態),終止時TRUE(signaled狀態)。

WaitForSingleObject & WaitForMultipleObjects

#include //dwMilliseconds為INFINITE時阻塞直到終止//終止(signaled狀態)返回WAIT_OBJECT_0,超時返回WAIT_TIMEOUTDWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);

該函數發生事件(變為signaled狀態)返回時,有時會把相應對象再次改為non-signaled狀態。

可以再次進入non-signaled狀態的內核對象稱為“auto-reset模式”的內核對象,不會自動跳轉到non-signaled狀態的內核對象稱為“manual-reset模式”的內核對象。

#include //bWaitAll為TRUE,所有內核對象變為signaled狀態時返回,//bWaitAll為FALSE,任一內核對象變為signaled狀態時返回//dwMilliseconds為INFINITE時阻塞直到終止//終止(signaled狀態)返回WAIT_OBJECT_0,超時返回WAIT_TIMEOUTDWORD WaitForMultipleObjects(DWORD nCount, const HANDLE *lphHandles, BOOL bWaitAll, DWORD dwMilliseconds);

thread2_win.c

#include #include #include  //_beginthreadex, _endthreadexunsigned WINAPI ThreadFunc(void *arg);int main(int argc, char *argv[]) {HANDLE hThread;DWORD wr;unsigned threadID;int param=5;hThread=(HANDLE)_beginthreadex(NULL, 0, ThreadFunc, (void*)&param, 0, &threadID);if(hThread==0) {puts("_beginthreadex() error");return -1;}if((wr=WaitForSingleObject(hThread, INFINITE))==WAIT_FAILED) {puts("thread wait error");return -1;}printf("wait result: %s\n", (wr==WAIT_OBJECT_0)?"signaled":"time-out");puts("end of main");return 0;}unsigned WINAPI ThreadFunc(void *arg) {int i;int cnt=*((int*)arg);for(i=0; i<cnt; i++) {Sleep(1000);puts("running thread");}return 0;}
cl /EHsc thread2_win.c /Fe:thread2_win.exethread2_win

thread3_win.c

#include #include #include #define NUM_THREAD 50unsigned WINAPI thread_inc(void *arg);unsigned WINAPI thread_des(void *arg);long long num=0;int main(int argc, char *argv[]) {HANDLE thread_id[NUM_THREAD];int i;printf("size long long: %d\n", sizeof(long long));for(i=0; i<NUM_THREAD; i++) {if(i%2)thread_id[i]=(HANDLE)_beginthreadex(NULL, 0, thread_inc, NULL, 0, NULL);elsethread_id[i]=(HANDLE)_beginthreadex(NULL, 0, thread_des, NULL, 0, NULL);}WaitForMultipleObjects(NUM_THREAD, thread_id, TRUE, INFINITE);printf("result: %lld\n", num);return 0;};unsigned WINAPI thread_inc(void *arg) {int i;for(i=0; i<50000000; i++)num+=1;return NULL;}unsigned WINAPI thread_des(void *arg) {int i;for(i=0; i<50000000; i++)num-=1;return NULL;}
cl /EHsc thread3_win.c /Fe:thread3_win.exethread3_win