Chapter 19 of TCP/IP network programming

Kernel Objects

definition

Resources created and managed by Windows operating system, including processes, threads, files, semaphores, mutexes, etc.

Different resource management methods are different.

  • File management, register and update file related data I/O
    Location, file open mode (read or write), etc.
  • Thread management, register and maintain thread ID, thread belonging process and other information.

In order to manage various resources by recording relevant information, the operating system generates data blocks (structure variables, kernel objects) in it.

Kernel objects are owned by the operating system

The creation, management and destruction timing of kernel objects are completed by the operating system.

Windows thread creation

Process and thread

Non display programs that create threads, applications with a single thread model.
Shows the program that creates a separate thread, the application of the multithreading model.
The main function runs based on threads. The process is a basket with threads, and the actual running body is threads.

Create thread

Integer handles that distinguish kernel objects, similar to Linux file descriptors.

#include <windows.h>
//Failed NULL
HANDLE CreateThread(
	LPSECURITY_ATTRIBUTES lpThreadAttributes,//Thread safety related information, NULL by default
	SIZE_T dwStackSize,//Thread stack size, 0 default size
	LPTHREAD_START_ROUTINE lpStartAddress,//function
	LPVOID lpParameter,//parameter
	DWORD dwCreationFlags, //The behavior of a thread after it is created. 0 thread enters the executable state immediately after it is created
	LPDWORD lpThreadId //Thread ID
);

The Windows thread is destroyed when the main function returns.

Creating thread safe functions

#include <process.h>
//Failed 0
unitptr_t _beginthreadex( //unitptr_t. 64 bit unsigned integer
	void *security,//Thread safety related information, NULL by default
	unsigned stack_size,//Thread stack size, 0 default size
	unsigned (*start_address)(void *),//function
	void *arglist,//parameter
	unsigned initflag, //The behavior of a thread after it is created. 0 thread enters the executable state immediately after it is created
	unsigned *thrdaddr //Thread ID
);
//_ beginthread invalidates the handle returned when the thread is created to prevent access to kernel objects

thread1_win.c

#include <stdio.h>
#include <windows.h>
#include <process.h> //_beginthreadex, _endthreadex
unsigned WINAPI ThreadFunc(void *arg);

//WINAPI, Windows inherent keyword, specifying parameter transfer direction, allocated stack return method and other function call related regulations.

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.exe
thread1_win

Threads belong to operating system management resources. With the creation of kernel objects, they return handles in order to reference kernel objects.

Handles distinguish kernel objects, kernel objects distinguish threads, and thread handles distinguish threads.

The integer value of the handle may be repeated in different processes, and the thread ID will not be repeated across processes.

Thread ID S distinguish all threads created by the operating system.

2 states of kernel objects

The information that needs special attention in the process of application implementation is given a certain "state". Thread termination state is also called signaled state, and non terminated state is called non signaled state.

Kernel object status and status viewing

The initial state of the kernel object of a process or thread is the non signaled state, and the terminated state is the signaled state.

The boolean variable indicates that the initial value is FALSE (non signaled state) and TRUE (signaled state) at termination.

WaitForSingleObject & WaitForMultipleObjects

#include <windows.h>

//When dwMilliseconds is INFINITE, block until terminated
//Terminated (signaled status) return WAIT_OBJECT_0, timeout return WAIT_TIMEOUT
DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);

When the function returns an event (changed to the signaled state), sometimes the corresponding object will be changed to the non signaled state again.

Kernel objects that can enter the non signaled state again are called "auto reset mode" kernel objects, and kernel objects that will not automatically jump to the non signaled state are called "manual reset mode" kernel objects.

#include <windows.h>
//bWaitAll is TRUE, which is returned when all kernel objects change to the signaled state,
//bWaitAll is FALSE, which is returned when any kernel object changes to the signaled state
//When dwMilliseconds is INFINITE, block until terminated
//Terminated (signaled status) return WAIT_OBJECT_0, timeout return WAIT_TIMEOUT
DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE *lphHandles, BOOL bWaitAll, DWORD dwMilliseconds);

thread2_win.c

#include <stdio.h>
#include <windows.h>
#include <process.h> //_beginthreadex, _endthreadex
unsigned 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.exe
thread2_win

thread3_win.c

#include <stdio.h>
#include <windows.h>
#include <process.h>

#define NUM_THREAD 50

unsigned 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);
		else
			thread_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.exe
thread3_win

Keywords: C++ network TCP/IP

Added by projectshifter on Sat, 15 Jan 2022 07:49:38 +0200