最近在看《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,就可以得到這個開源庫了。