最近在看《C++多核進階編程》這本書,收集了些有用的東西,方便在windows下使用POSIX標準進行Pthread開發,有利於跨平台。
--------------------------------------------------
windows下使用pthread庫時間:2010-01-27 07:41來源:羅索工作室 作者:落鶴生 點擊:1220次
我聽很多人都說pthreads對Windows的相容性不好,但我又沒用過,也根本不知道到底好,還是不好,只不過我看ffmpeg都有在用pthreads,而做流媒體的話ffmpeg是必不可少的,那是否ffmpeg選錯了,它該怎麼搞一套類似pthreads的東西出來呢?問題是它沒有。所以我想試試看。
1 下載庫
建議大家下載:ftp://sources.redhat.com/pub/pthreads-win32/這個自解壓檔案,壓縮包裡的pthreads.2目錄是源碼,Pre-built.2目錄是編譯所需的標頭檔和庫檔案。
如果要自行編譯請看這裡:
使用微軟的CL來編譯:
rem cl.bat
cl.exe main.cpp /c /I"c:/pthreads-w32-2-7-0-release/Pre-built.2/include"
link.exe /out:main_cl.exe main.obj /LIBPATH:"c:/pthreads-w32-2-7-0-release/Pre-built.2/lib" pthreadVC2.lib
pause
或者使用GCC來編譯:
rem gcc.bat
g++.exe -o main.o -c main.cpp -I"c:/pthreads-w32-2-7-0-release/Pre-built.2/include"
g++.exe -o main_gcc.exe main.o "c:/pthreads-w32-2-7-0-release/Pre-built.2/lib/libpthreadGC2.a"
pause
嘿嘿!開源就是好啊,跨平台實現得如此容易
2 vc的設定
添加執行庫、目錄、庫檔案的路徑;
01. //main.cpp
02. #include <stdio.h>
03. #include <pthread.h>
04. #include <assert.h>
05.
06. void* Function_t(void* Param)
07. {
08. printf("我是線程! ");
09. pthread_t myid = pthread_self();
10. printf("線程ID=%d ", myid);
11. return NULL;
12. }
13.
14. int main()
15. {
16. pthread_t pid;
17. pthread_attr_t attr;
18. pthread_attr_init(&attr);
19. pthread_attr_setscope(&attr, PTHREAD_SCOPE_PROCESS);
20. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
21. pthread_create(&pid, &attr, Function_t, NULL);
22. printf("======================================== ");
23. getchar();
24. pthread_attr_destroy(&attr);
25. return 1;
26. }
3 測試
編寫程式,添加項目中庫檔案,編譯運行即可。
2:在VC下使用POSIX標準的線程
POSIX下的很多東西我都很喜歡,其中就包括pthread。不過跟使用socket面臨同樣的問題,在Linux下偵錯工具並沒有VC下方便。所以,希望在VC下可以pthread寫東西,調試沒有問題的話可以在各個平台下使用。
在網上找了一些資料,發現VC下使用pthread也是異常簡單啊,呵呵,記錄下來,備用~~~
有一個叫做POSIX Threads for Win32的項目,專門為win32開發了一個pthread的lib,利用它,可以很方便的在win32下實現pthread的應用。我這裡使用到的是2.8.0版本的POSIX Threads for Win32,:將下載到的exe解壓之後,會得到三個目錄:
其中,Pre-built.2中是已經編譯好的lib以及dll,同時包含了一些必要的標頭檔。將其中的include檔案夾和lib檔案夾 copy到VC的安裝目錄下,例如,我的是VC6.0的環境,預設安裝,則,需要copy到:C:/Program Files/Microsoft Visual Studio/VC98
接著,在編程的時候,引入pthreadVC2.lib即可:
1: #pragma comment(lib, "pthreadVC2.lib")
剩下的步驟,就和Linux下一樣了,盡情享用吧^_^
-------------------------------------
Windows中的pthread程式(2009-06-23 19:47:56)
轉載
閑著沒事做,找了點pthread-win32的資料看了看,寫了個無聊的程式。pthread的使用倒沒有什麼,倒是注意到了兩個細節問題:
1 在微軟的編譯器中,可以在標頭檔開始處加#pragma once,防止檔案被包含兩次。它與更通用的#ifdef稍微不同,僅用於微軟的編譯器,它防止一個物理檔案被包含兩次,卻不能防止相同內容的不同檔案被包含兩次。當然,這不是問題,相同內容包含兩次會出編譯錯誤的。
2 在多線程程式中,應該使用多線程的C執行階段程式庫。有兩種方法來實現:
(1)在工程設定對話方塊中,選擇【C/C++】選項卡,再在【Use run-time library】下拉式清單中選擇多線程庫
(2)使用預先處理命令。我是摸索了一會兒才發現正確的方法的:
#pragma comment(linker,"/NODEFAULTLIB:libcd /DEFAULTLIB:libcmt")
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <pthread.h>
#include "myheader.h"
#include "myheader.h"
#pragma comment(lib,"pthreadVSE2")
#pragma comment(linker,"/NODEFAULTLIB:libcd /DEFAULTLIB:libcmt")
#define THREAD_NUM 10
static pthread_cond_t g_cond;
static pthread_mutex_t g_mutex;
static int g_index_wakeup;
static int g_exit_count;
typedef struct
{
pthread_key_t key;
int index;
int num;
}THREAD_DATA;
static void destroy_key(void* p)
{
THREAD_DATA* p_data;
p_data = (THREAD_DATA*)p;
printf("### thread %2d destroy key ###/n",p_data->index);
free(p);
if (++g_exit_count == THREAD_NUM)
{
pthread_cond_broadcast(&g_cond);
}
}
static void* thread_proc(void* p)
{
THREAD_DATA* p_data;
p_data = (THREAD_DATA*)p;
if (0 != pthread_key_create(&(p_data->key),destroy_key)) return NULL;
pthread_setspecific(p_data->key,p_data);
srand(time(NULL)+(int)p);
p_data->num = rand();
while (1)
{
p_data = (THREAD_DATA*)pthread_getspecific(p_data->key);
pthread_mutex_lock(&g_mutex);
if (-100 == g_index_wakeup)
{
pthread_mutex_unlock(&g_mutex);
break;
}
else if (p_data->index == g_index_wakeup)
{
printf("thread %d: the num is %d now./n",p_data->index,p_data->num);
p_data->num += rand();
g_index_wakeup = -1;
pthread_cond_broadcast(&g_cond);
}
pthread_mutex_unlock(&g_mutex);
Sleep(50);
}
return NULL;
}
int main(int argc,char* argv[])
{
pthread_t pid;
pthread_attr_t attr;
THREAD_DATA* p_data;
int cur;
pthread_mutex_init(&g_mutex,NULL);
pthread_cond_init(&g_cond,NULL);
g_index_wakeup = -1;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
for(cur = 0; cur < THREAD_NUM; cur++)
{
p_data = (THREAD_DATA*)malloc(sizeof(THREAD_DATA));
p_data->index = cur + 1;
pthread_create(&pid,&attr,thread_proc,p_data);
}
pthread_attr_destroy(&attr);
srand(time(NULL));
cur = 0;
while(1)
{
pthread_mutex_lock(&g_mutex);
if (-1 != g_index_wakeup)
{
pthread_cond_wait(&g_cond,&g_mutex);
}
do
{
g_index_wakeup = rand()%THREAD_NUM+1;
} while ((g_index_wakeup < 0) || (g_index_wakeup > THREAD_NUM));
if (++cur > THREAD_NUM)
{
g_exit_count = 0;
g_index_wakeup = -100;
printf("/n/n");
pthread_cond_wait(&g_cond,&g_mutex);
pthread_mutex_unlock(&g_mutex);
break;
}
else
{
printf("/n### Wake up thread %d ###/n",g_index_wakeup);
pthread_mutex_unlock(&g_mutex);
}
}
pthread_mutex_destroy(&g_mutex);
pthread_cond_destroy(&g_cond);
return 0;
}
---------------------------------------------------------------------------------
error LNK2005: xxx already defined in libcmt.lib(xxx.obj) MSVCRT.lib
參考:
這個錯誤是微軟設計錯誤,因此如果遇到這個錯誤,我們只能躲過這個連結錯誤。具體的辦法就是將那個提示出錯的庫放到另外一個庫的前面。另外選擇不同的C函數庫,可能會引起這個錯誤。MS, C有兩種C函數庫,一種是普通的函數庫:LIBC.LIB,不支援多線程。另外一種是支援多線程的:msvcrt.lib。如果一個工程裡,這兩種函數庫混合使用,可能會引起這個錯誤。因此建議使用支援多線程的msvcrt.lib。
需要注意的是,當使用其他的庫的時候最容易產生這種錯誤,例如boost和wxWindow使用/MD來編譯的,也就是使用支援多線程的C函數庫。這時候如果自己的程式沒有指明/MD的話,就會提示兩種C函數衝突,並且還有LNK2005錯誤。因此如果使用boost,wxWindow的話,需要指明/MD。
msvcrt.lib是VC中的Multithreaded DLL 版本的C執行階段程式庫,而libcmt.lib是Multithreaded的執行階段程式庫。在同一個項目中,所有的源檔案必須連結相同的C執行階段程式庫。如果某一檔案用了Multithreaded DLL版本,而其他檔案用了Single-Threaded或者Multithreaded版本的庫,也就是說用了不同的庫,就會導致這個警告的出現。
VC中的C執行階段程式庫一共有6種
Single-threaded (libc.lib) libcmt.lib, msvcrt.lib, libcd.lib, libcmtd.lib, msvcrtd.lib
Multithreaded (libcmt.lib) libc.lib, msvcrt.lib, libcd.lib, libcmtd.lib, msvcrtd.lib
Multithreaded using DLL (msvcrt.lib) libc.lib, libcmt.lib, libcd.lib, libcmtd.lib, msvcrtd.lib
Debug Single-threaded (libcd.lib) libc.lib, libcmt.lib, msvcrt.lib, libcmtd.lib, msvcrtd.lib
Debug Multithreaded (libcmtd.lib) libc.lib, libcmt.lib, msvcrt.lib, libcd.lib, msvcrtd.lib
Debug Multithreaded using DLL (msvcrtd.lib) libc.lib, libcmt.lib, msvcrt.lib, libcd.lib, libcmtd.lib
這個在C++ ->Code Generation-->runtime library 中設定,實際上和靜態dll和動態dll有關
解決辦法:
Project Settings:
-> Configration Properties -> Linker -> Input -> Ignore Specific Library: libcmtd
libcmtd 這個庫有時候不能忽略,忽略後會有不能解析的外部符號錯誤
其實有個方便的方法 連結時加入參數 /FORCE:MULTIPLE
-------------------------------------------------------------------------------------------
google一下POSIX Threads for Win32,就可以得到這個開源庫了。