介紹
在現代操作系統中,每個進程都有自己的地址空間和一個控制線程。然而,在實踐中,我們經常遇到需要在單個進程中執行多個并發任務并訪問相同進程組件的情況:結構、打開的文件描述符等。
在任何情況下組織多線程模型都需要同時訪問相同的資源。本文提供了有關 Windows 和 Linux 操作系統中線程的一般信息,然后介紹了防止訪問共享資源的同步機制[1] 。
對于那些處理從一個系統移植到另一個系統的應用程序或在一個系統中創建多線程應用程序并想知道它在另一個系統中如何實際實現的人來說,這篇文章將會很有趣。本文對于那些從未編寫過多線程應用程序但計劃在未來這樣做的人也很有用。
線程概念
這些線程是做什么用的?為什么我們不能只創建流程?后一種范式已經工作了很多年,但是流程創建有一些缺點,下面舉幾個例子:
進程創建操作是資源密集型的。
進程需要復雜的機制來訪問相同的資源(命名或未命名的管道、消息隊列、套接字等),而線程會自動獲得對相同地址空間的訪問權。
多線程進程的性能高于單線程。
多線程允許多個線程作為一個進程的一部分執行。具有線程的編程模型為開發人員提供了對同時執行的舒適抽象。具有線程的程序的優點之一是它在具有多核處理器的計算機上運行得更快。線程在創建時幾乎不使用資源,或者額外的插件,例如資源訪問機制;此外,線程的性能和應用程序交互性更高。除了地址空間,所有線程都使用:
工藝規定
信號處理程序(處理信號的設置)
當前目錄
用戶和組標識符
同時,每個線程都有自己的:
線程標識符
堆
寄存器集
信號屏蔽
優先
使用線程的主要函數
在通過 exec 調用啟動程序時,會創建一個主線程(初始線程)。輔助線程是通過調用 Linux 的 pthread_create 或 Windows 的 _beginthread(ex) 創建的。
讓我們更仔細地看看 Linux 的線程創建:
#include
int pthread_create(
pthread_t *tid,
const pthread_attr_t *attr,
void *(*func)(void *),
void *arg
);
/* Returns 0 in case of a successful completion, positive value in case of an error*/
每個線程都有它的標識符——pthread_t——和屬性:優先級、初始堆棧大小、守護進程特性。創建線程時,需要指明將要執行的函數地址(func),以及單指針參數(arg)。Linux 中的線程應顯式退出——通過調用pthread_exit函數——或隱式退出——通過從該函數返回[2]。如果在問題的條件下需要將多個參數傳遞給線程,則必須使用帶參數的結構地址。
在 Windows 中,線程是在_beginthread(ex)或CreateThread函數的幫助下創建的。兩者都是 ?-runtime 調用,它們之間的主要區別在于CreateThread是一個“原始”Win32 API,而_beginthread(ex)在其內部調用CreateThread 。在本文中,我們將討論_beginthread(ex)函數。_beginthreadex的語法如下:
uintptr_t _beginthreadex(
void *security,
unsigned stack_size,
unsigned(__stdcall *start_address)(void *),
void *arglist,
unsigned initflag,
unsigned *thrdaddr
);
可以觀察到pthread_create和_beginthreadex調用之間有一些模糊的相似性;但是,也存在差異。?hus,在 Windows 中:security– 指向SECURITY_ATTRIBUTES結構的指針,thrdaddr– 指向接收線程標識符的 32 位變量。
讓我們考慮以下線程創建示例:
#include
#ifdef __PL_WINDOWS__
#include
#endif //__PL_WINDOWS__
#ifdef __PL_LINUX__
#include
#endif //__PL_LINUX__
#define STACK_SIZE_IN_BYTES (2097152) //2MB
#ifdef __PL_WINDOWS__
unsigned int __stdcall process_command_thread(void) {
#endif //__PL_WINDOWS__
#if defined (__PL_LINUX__) || (__PL_SOLARIS__) || (__PL_MACOSX__)
void *process_command_thread(void *p) {
#endif //(__PL_LINUX__) || (__PL_SOLARIS__) || (__PL_MACOSX__)
printf("Hello from process command thread\n");
return 0;
}
int main(int argc, char *argv[])
{
#ifdef __PL_WINDOWS__
DWORD process_command_thread_id;
HANDLE h_process_command_thread;
h_process_command_thread = (HANDLE)_beginthreadex(
NULL,
STACK_SIZE_IN_BYTES,
process_command_thread,
NULL,
0,
(unsigned long *)&process_command_thread_id
);
if (h_process_command_thread == NULL)
return -1;
#endif //__PL_WINDOWS__
#ifdef __PL_LINUX__
pthread_t h_process_command_thread;
int h_process_command_thread_initialized;
int ret;
ret = pthread_create(
&h_process_command_thread,
NULL,
process_command_thread,
NULL
);
if (ret != 0)
return -1;
h_process_command_thread_initialized = 1;
#endif // __PL_LINUX__
printf("Hello from main thread\n");
return 0;
}
輸出將如下:
很容易注意到 process_command_thread 沒有以可視方式運行。當用于線程管理的內部結構被pthread_create或_beginthreadex函數初始化時,主線程完成執行。在 Linux 中調用 pthread_join 后,我們可以期待線程退出。
int pthread_join(pthread_t tid, void **retval);
線程可以是可連接的(默認情況下)或分離的。當一個可連接線程終止時,信息(標識符、終止狀態、線程計數器等)會一直保存到調用pthread_join為止。
在 Windows 操作系統中,可以認為等待函數之一類似于pthread_join。等待函數系列允許線程中斷其執行并等待資源被釋放。讓我們看一下pthread_join的類似物,即WaitForSingleObject:
DWORD WaitForSingleObject(HANDLE hObject, DWORD dwMilliseconds);
調用此函數時,第一個參數hObject標識內核對象。該對象可能處于以下兩種狀態之一:“空閑”或“忙碌”。
第二個參數dwMilliseconds表示線程準備等待釋放對象的毫秒數。
以下示例說明了pthread_join\WaitForSingleObject調用:
#ifdef __PL_WINDOWS__
DWORD status = WaitForSingleObject(
h_process_command_thread,
INFINITE
);
switch (status) {
case WAIT_OBJECT_0:
// The process terminated
break;
case WAIT_TIMEOUT:
// The process did not terminate within timeout
break;
case WAIT_FAILED:
// Bad call to function
break;
}
#endif //__PL_WINDOWS__
#ifdef __PL_LINUX__
int status = pthread_join(
h_process_command_thread,
NULL
);
switch (status) {
case 0:
// The process terminated
break;
case default:
// Bad call to function
break;
}
#endif //__PL_LINUX__
#ifdef __PL_WINDOWS__
//Windows code
#endif //__PL_WINDOWS__
#ifdef __PL_LINUX__
//Code for UNIX OS systems
#endif //__PL_LINUX__
審核編輯:郭婷
-
Linux
+關注
關注
87文章
11296瀏覽量
209353 -
WINDOWS
+關注
關注
3文章
3541瀏覽量
88633 -
操作系統
+關注
關注
37文章
6808瀏覽量
123290
發布評論請先 登錄
相關推薦
評論