 |
級別: 初級
Nam Keung (mailto:namkeung@us.ibm.com), 高級程序員, IBM
2005 年 4 月 21 日
將您的 Win32 C/C++ 應(yīng)用程序遷移到 POWER™ 上的 Linux™,并從信號(semaphore)應(yīng)用程序接口(application program interface,API)的角度理解 Win32 到 Linux 的映射。Nam Keung 將通過詳細的代碼示例來為您描述這一過程。
介紹
本系列第三篇文章從信號的角度闡述了 Win32 C/++ 應(yīng)用程序向 POWER 上的 Linux 的遷移。本系列的第 1 部分介紹了 Win32 API 映射,第 2 部分從互斥(mutex)API 的角度集中闡述了如何將 Win32 映射到 Linux。在繼續(xù)閱讀之前,建議您先去閱讀本系列的第 1 部分和第 2 部分。
信號
信號是包含有一個正數(shù)的資源。信號允許進程通過一個單一的原子操作來測試和設(shè)置那個整數(shù)的值,以此實現(xiàn)同步。通常,信號的主要用途是同步某個線程與其他線程的動作。在多個進程競爭訪問同一操作系統(tǒng)資源時,這也是協(xié)調(diào)或者同步那些行為的一種實用技術(shù)。
Linux 支持 Portable Operating System Interface(POSIX)信號以及 pthread 條件變量,以此來映射 Win32 信號 API。它們各有其優(yōu)缺點。您應(yīng)該基于應(yīng)用程序的邏輯來判斷使用哪種方法。在映射事件信號的過程中需要考慮的方面包括:
- 信號的類型:Win32 既支持有名稱的事件信號,也支持無名稱的事件信號。有名稱的信號是在多個進程間共享的。Linux 不支持這種方案。本文中列出的一個進程間通信(Inter-Process Communication,IPC)消息隊列示例代碼將向您展示如何來解決此問題。
- 初始狀態(tài):在 Win32 中,信號可能會有初始值。在 Linux 中,POSIX 信號支持此功能,但 pthreads 不支持。在使用 pthreads 時您需要考慮到這一點。
- 超時:Win32 事件信號支持定時等待。在 Linux 中,POSIX 信號實現(xiàn)只支持不確定的等待(阻塞)。pthreads 實現(xiàn)既支持阻塞也支持超時。
pthread_cond_timedwait() 調(diào)用能給出等待期間的超時的值,pthread_cond_wait() 則用于不確定的等待。
- 發(fā)信號:在 Win32 中,發(fā)出信號會喚醒等待那個信號的所有線程。在 Linux 中,POSIX 線程實現(xiàn)一次只喚醒一個線程。pthreads 實現(xiàn)的
pthread_cond_signal() 調(diào)用會喚醒一個線程,pthread_cond_broadcast() 調(diào)用會向所有等待那個信號的線程發(fā)出信號。
表 1. 信號映射表
Win32 |
pthread Linux |
POSIX |
CreateSemaphore |
pthread_mutex_init(&(token)->mutex, NULL)) pthread_cond_init(&(token)->condition, NULL)) |
sem_init |
CloseHandle (semHandle) |
pthread_mutex_destroy(&(token->mutex)) pthread_cond_destroy(&(token->condition)) |
sem_destroy |
ReleaseSemaphore(semHandle, 1, NULL) |
pthread_cond_signal(&(token->condition)) |
sem_post |
WaitForSingleObject(semHandle, INFINITE) WaitForSingleObject(semHandle, timelimit) |
pthread_cond_wait(&(token->condition), &(token->mutex)) pthread_cond_timedwait(&(token ->condition), &(token->mutex)) |
sem_wait sem_trywait |
條件變量
條件變量讓開發(fā)者能夠?qū)崿F(xiàn)一個條件,在這個條件下線程執(zhí)行然后被阻塞。Microsoft® Win32 接口本身不支持條件變量。為解決此缺憾,我使用 POSIX 條件變量模擬同步原語,并在一系列文章中對此進行了概述。在 Linux 中,它可以確保因某條件被阻塞的線程,當(dāng)那個條件改變時,會被解除阻塞。它還允許您原子地(atomically)解除互斥的鎖定,并等待條件變量,而不會有干涉其他線程的可能。不過,每個條件變量都應(yīng)該伴有一個互斥。前面的表 1 給出了用于線程間同步的 pthread 條件變量。
創(chuàng)建信號
在 Win32 中,CreateSemaphore 函數(shù)可以創(chuàng)建一個有名稱的或者無名稱的信號對象。Linux 不支持有名稱的信號。
清單 1. 創(chuàng)建信號
HANDLE CreateSemaphore (
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
LONG lInitialCount,
LONG lMaximunCount,
LPCTSTR lpName
);
|
在 Linux 中,sem_init() 調(diào)用會創(chuàng)建一個 POSIX 信號:
清單 2. POSIX 信號
int sem_init(sem_t *sem, int pshared, unsigned int value
|
Linux 使用 pthread_condition_init 調(diào)用在當(dāng)前進程內(nèi)創(chuàng)建信號對象,在其中維持一個在零與最大值之間的計數(shù)值。每次有某個線程完成對信號的等待,這個計數(shù)值會減小,而每次當(dāng)某個線程釋放這個信號時,計數(shù)值增加。當(dāng)計數(shù)值成為零時,信號對象的狀態(tài)成為 non-signaled。
清單 3. 創(chuàng)建信號對象的 pthread_condition_init 調(diào)用
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
|
清單 4. Win32 示例代碼
HANDLE semHandle;
semHandle = CreateSemaphore(NULL, 0, 256000, NULL);
/* Default security descriptor */
if( semHandle == (HANDLE) NULL)
/* Semaphore object without a name */
{
return RC_OBJECT_NOT_CREATED;
}
|
清單 5. 相應(yīng)的 Linux 代碼
typedef struct
{
pthread_mutex_t mutex;
pthread_cond_t condition;
int semCount;
}sem_private_struct, *sem_private;
sem_private token;
token = (sem_private) malloc(sizeof(sem_private_struct));
if(rc = pthread_mutex_init(&(token->mutex), NULL))
{
free(token);
return RC_OBJECT_NOT_CREATED;
}
if(rc = pthread_cond_init(&(token->condition), NULL))
{
pthread_mutex_destroy( &(token->mutex) );
free(token);
return RC_OBJECT_NOT_CREATED;
}
token->semCount = 0;
|
銷毀事件信號
Win32 使用 CloseHandle 來刪除由 CreateSemaphore 所創(chuàng)建的信號對象。
清單 6. 銷毀事件信號
BOOL CloseHandle (HANDLE hObject);
|
Linux POSIX 信號使用 sem_destroy() 來銷毀無名稱的信號。
清單 7. sem_destroy()
int sem_destroy(sem_t *sem);
|
在 Linux pthreads 中,使用 pthread_cond_destroy() 來銷毀條件變量。
清單 8. pthread_cond_destroy()
int pthread_cond_destroy(pthread_cond_t *cond);
|
清單 9. Win32 代碼和相應(yīng)的 Linux 代碼
Win32 代碼 |
相應(yīng)的 Linux 代碼 |
CloseHandle(semHandle); |
pthread_mutex_destroy(&(token->mutex));
pthread_cond_destroy(&(token->condition));
free (token); |
發(fā)布事件信號
在 Win32 中,ReleaseSemaphore 函數(shù)會令指定的信號對象的計數(shù)值增加指定數(shù)量。
清單 10. ReleaseSemaphore 函數(shù)
BOOL ReleaseSemaphore(
HANDLE hSemaphore,
LONG lReleaseCount,
LPLONG lpPreviousCount
);
|
Linux POSIX 信號使用 sem_post() 來發(fā)布事件信號。這將喚醒阻塞于此信號的所有線程。
清單 11. sem_post()
int sem_post(sem_t * sem);
|
在 Linux 中,pthread_cond_signal 會喚醒等待某個條件變更的某個線程。Linux 調(diào)用這個函數(shù)來為此對象所標(biāo)識的信號發(fā)布一個事件完成信號。調(diào)用的線程增加那個信號的值。如果信號的值從零開始增加,而且 pthread_cond 中有任何線程被阻塞,那么請等待這個信號,因為其中一個會被喚醒。默認情況下,實現(xiàn)可以選擇任意的正在等待的線程。
清單 12. pthread_cond_signal
int pthread_cond_signal(pthread_cond_t *cond);
|
清單 13. Win32 代碼和相應(yīng)的 Linux 代碼
Win32 代碼 |
相應(yīng)的 Linux 代碼 |
ReleaseSemaphore(semHandle, 1, NULL) |
if (rc = pthread_mutex_lock(&(token->mutex))) return RC_SEM_POST_ERROR;
token->semCount ++;
if (rc = pthread_mutex_unlock(&(token->mutex))) return RC_SEM_POST_ERROR;
if (rc = pthread_cond_signal(&(token->condition))) return RC_SEM_POST_ERROR; |
等待事件信號
Win32 調(diào)用 WaitForSingleObject 函數(shù)來等待所需要的信號上事件的完成。當(dāng)?shù)却龁我痪€程同步對象時,可以使用此方法。當(dāng)對象被設(shè)置發(fā)出信號或者超時時間段結(jié)束時,這個方法會得到通知。如果時間間隔是 INFINITE,那么它就會無止境地等待下去。
清單 14. WaitForSingleObject 函數(shù)
DWORD WaitForSingleObject(
HANDLE hHANDLE,
DWORD dwMilliseconds
);
|
使用 WaitForMultipleObjects 函數(shù)來等待多個被通知的對象。在信號線程同步對象中,當(dāng)計數(shù)器變?yōu)榱銜r,對象是 non-signaled。
清單 15. WaitForMultipleObjects 函數(shù)
DWORD WaitForMultipleObjects(
DWORD nCount,
Const HANDLE* lpHandles,
BOOL bWaitAll,
DWORD dwMilliseconds
);
|
Linux POSIX 信號使用 sem_wait() 來掛起發(fā)出調(diào)用的線程,直到信號擁有了非零的計數(shù)值。然后它自動地減少信號的計數(shù)值。
清單 16. sem_wait() 函數(shù)
int sem_wait(sem_t * sem);
|
在 POSIX 信號中不能使用超時選項。不過,您可以通過在某個循環(huán)中執(zhí)行非阻塞的 sem_trywait() 來完成此功能,它會計算超時的值。
清單 17. sem_trywait() 函數(shù)
int sem_trywait(sem_t * sem);
|
在 Linux 中,pthread_cond_wait() 會阻塞發(fā)出調(diào)用的線程。發(fā)出調(diào)用的線程會減小那個信號。如果當(dāng) pthread_cond_wait 被調(diào)用時信號是零,則 pthread_cond_wait() 就會阻塞,直到另一個線程增加了那個信號的值。
清單 18. pthread_cond_wait() 函數(shù)
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
|
pthread_cond_wait 函數(shù)首先釋放相關(guān)聯(lián)的 external_mutex of type pthread_mutex_t ,當(dāng)調(diào)用者檢查條件表達式時必須持有它。
清單 19. Win32 代碼和相應(yīng)的 Linux 代碼
Win32 代碼 |
相應(yīng)的 Linux 代碼 |
DWORD retVal;
retVal = WaitForSingleObject(semHandle, INFINITE);
if (retVal == WAIT_FAILED) return RC_SEM_WAIT_ERROR |
if (rc = pthread_mutex_lock(&(token->mutex))) return RC_SEM_WAIT_ERROR;
while (token->semCount <= 0) { rc = pthread_cond_wait(&(token->condition), &(token->mutex)); if (rc &&errno != EINTR ) break; } token->semCount--;
if (rc = pthread_mutex_unlock(&(token->mutex))) return RC_SEM_WAIT_ERROR; |
如果您需要在指定的一段時間內(nèi)阻塞發(fā)出調(diào)用的線程,那么請使用 pthread_cond_timewait 來阻塞它。調(diào)用這個方法來等待所需要信號上某個事件的完成,等待指定的一段時間。
清單 20. pthread_cond_timewait
int pthread_cond_timewait(
pthread_cond_t *cond,
pthread_mutex_t *mutex,
timespec *tm
);
|
清單 21. Win32 代碼和相應(yīng)的 Linux 代碼
Win32 代碼 |
相應(yīng)的 Linux 代碼 |
retVal = WaitForSingleObject(SemHandle, timelimit);
if (retVal == WAIT_FAILED) return RC_SEM_WAIT_ERROR;
if (retVal == WAIT_TIMEOUT) return RC_TIMEOUT; |
int rc; struct timespec tm; struct timeb tp; long sec, millisec;
if (rc = pthread_mutex_lock(&(token->mutex))) return RC_SEM_WAIT_ERROR;
sec = timelimit / 1000; millisec = timelimit % 1000; ftime( &tp ); tp.time += sec; tp.millitm += millisec; if( tp.millitm > 999 ) { tp.millitm -= 1000; tp.time++; } tm.tv_sec = tp.time; tm.tv_nsec = tp.millitm * 1000000 ;
while (token->semCount <= 0) { rc = pthread_cond_timedwait(&(token->condition), &(token->mutex), &tm); if (rc && (errno != EINTR) ) break; } if ( rc ) { if ( pthread_mutex_unlock(&(token->mutex)) ) return RC_SEM_WAIT_ERROR );
if ( rc == ETIMEDOUT) /* we have a time out */ return RC_TIMEOUT );
return RC_SEM_WAIT_ERROR );
} token->semCount--;
if (rc = pthread_mutex_unlock(&(token->mutex))) return RC_SEM_WAIT_ERROR; |
POSIX 信號示例代碼
清單 22 使用 POSIX 信號來實現(xiàn)線程 A 和 B 之間的同步:
清單 22. POSIX 信號示例代碼
sem_t sem; /* semaphore object */
int irc; /* return code */
/* Initialize the semaphore - count is set to 1*/
irc = sem_init (sem, 0,1)
...
/* In Thread A */
/* Wait for event to be posted */
sem_wait (&sem);
/* Unblocks immediately as semaphore initial count was set to 1 */
.......
/* Wait again for event to be posted */
sem_wait (&sem);
/* Blocks till event is posted */
/* In Thread B */
/* Post the semaphore */
...
irc = sem_post (&sem);
/* Destroy the semaphore */
irc = sem_destroy(&sem);
|
進程內(nèi)信號示例代碼
清單 23. Win32 進程內(nèi)信號示例代碼
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
void thrdproc (void *data); // the thread procedure (function)
to be executed
HANDLE semHandle;
int
main( int argc, char **argv )
{
HANDLE *threadId1;
HANDLE *threadId2;
int hThrd;
unsigned stacksize;
int arg1;
if( argc < 2 )
arg1 = 7;
else
arg1 = atoi( argv[1] );
printf( "Intra Process Semaphor test.\n" );
printf( "Start.\n" );
semHandle = CreateSemaphore(NULL, 1, 65536, NULL);
if( semHandle == (HANDLE) NULL)
{
printf("CreateSemaphore error: %d\n", GetLastError());
}
printf( "Semaphor created.\n" );
if( stacksize < 8192 )
stacksize = 8192;
else
stacksize = (stacksize/4096+1)*4096;
hThrd = _beginthread( thrdproc, // Definition of a thread entry
NULL,
stacksize,
"Thread 1");
if (hThrd == -1)
return RC_THREAD_NOT_CREATED);
*threadId1 = (HANDLE) hThrd;
hThrd = _beginthread( thrdproc, // Definition of a thread entry
NULL,
stacksize,
“Thread 2");
if (hThrd == -1)
return RC_THREAD_NOT_CREATED);
*threadId2 = (HANDLE) hThrd;
printf( "Main thread sleeps 5 sec.\n" );
sleep(5);
if( ! ReleaseSemaphore(semHandle, 1, NULL) )
printf("ReleaseSemaphore error: %d\n", GetLastError());
printf( "Semaphor released.\n" );
printf( "Main thread sleeps %d sec.\n", arg1 );
sleep (arg1);
if( ! ReleaseSemaphore(semHandle, 1, NULL) )
printf("ReleaseSemaphore error: %d\n", GetLastError());
printf( "Semaphor released.\n" );
printf( "Main thread sleeps %d sec.\n", arg1 );
sleep (arg1);
CloseHandle(semHandle);
printf( "Semaphor deleted.\n" );
printf( "Main thread sleeps 5 sec.\n" );
sleep (5);
printf( "Stop.\n" );
return OK;
}
void
thread_proc( void *pParam )
{
DWORD retVal;
printf( "\t%s created.\n", pParam );
retVal = WaitForSingleObject(semHandle, INFINITE);
if (retVal == WAIT_FAILED)
return RC_SEM_WAIT_ERROR;
printf( "\tSemaphor blocked by %s. (%lx)\n", pParam, retVal);
printf( "\t%s sleeps for 5 sec.\n", pParam );
sleep(5);
if( ! ReleaseSemaphore(semHandle, 1, NULL) )
printf("ReleaseSemaphore error: %d\n", GetLastError());
printf( "\tSemaphor released by %s.)\n", pParam);
}
|
清單 24. 相應(yīng)的 Linux 進程內(nèi)信號示例代碼
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
void thread_proc (void * data);
pthread_mutexattr_t attr;
pthread_mutex_t mutex;
typedef struct
{
pthread_mutex_t mutex;
pthread_cond_t condition;
int semCount;
}sem_private_struct, *sem_private;
sem_private token;
int main( int argc, char **argv )
{
pthread_t threadId1;
pthread_t threadId2;
pthread_attr_t pthread_attr;
pthread_attr_t pthread_attr2;
int arg1;
int rc;
if( argc < 2 )
arg1 = 7;
else
arg1 = atoi( argv[1] );
printf( "Intra Process Semaphor test.\n" );
printf( "Start.\n" );
token =(sem_private) malloc (sizeof (sem_private_struct));
if(rc = pthread_mutex_init( &(token->mutex), NULL))
{
free(token);
return 1;
}
if(rc = pthread_cond_init(&(token->condition), NULL))
{
printf( "pthread_condition ERROR.\n" );
pthread_mutex_destroy( &(token->mutex) );
free(token);
return 1;
}
token->semCount = 0;
printf( "Semaphor created.\n" );
if (rc = pthread_attr_init(&pthread_attr))
{
printf( "pthread_attr_init ERROR.\n" );
exit;
}
if (rc = pthread_attr_setstacksize(&pthread_attr, 120*1024))
{
printf( "pthread_attr_setstacksize ERROR.\n" );
exit;
}
if (rc = pthread_create(&threadId1,
&pthread_attr,
(void*(*)(void*))thread_proc,
"Thread 1" ))
{
printf( "pthread_create ERROR.\n" );
exit;
}
if (rc = pthread_attr_init(&pthread_attr2))
{
printf( "pthread_attr_init2 ERROR.\n" );
exit;
}
if (rc = pthread_attr_setstacksize(&pthread_attr2, 120*1024))
{
printf( "pthread_attr_setstacksize2 ERROR.\n" );
exit;
}
if (rc = pthread_create(&threadId2,
&pthread_attr2,
(void*(*)(void*))thread_proc,
"Thread 2" ))
{
printf( "pthread_CREATE ERROR2.\n" );
exit ; // EINVAL, ENOMEM
}
printf( "Main thread sleeps 5 sec.\n" );
sleep( 5 );
if (rc = pthread_mutex_lock(&(token->mutex)))
{
printf( "pthread_mutex_lock ERROR 1.\n" );
return 1;
}
token->semCount ++;
if (rc = pthread_mutex_unlock&(token->mutex)))
{
printf( "pthread_mutex_unlock ERROR 1.\n" );
return 1;
}
if (rc = pthread_cond_signal(&(token->condition)))
{
printf( "pthread_cond_signal ERROR1.\n" );
return 1;
}
printf( "Semaphor released.\n" );
printf( "Main thread sleeps %d sec.\n", arg1 );
sleep( arg1 );
if (rc = pthread_mutex_lock(&(token->mutex)))
{
printf( "pthread_mutex_lock ERROR.\n" );
return 1;
}
token->semCount ++;
if (rc = pthread_mutex_unlock(&(token->mutex)))
{
printf( "pthread_mutex_lock ERROR.\n" );
return 1;
}
if (rc = pthread_cond_signal(&(token->condition)))
{
printf( "pthread_cond_signal ERROR.\n" );
return 1;
}
printf( "Semaphor released.\n" );
printf( "Main thread sleeps %d sec.\n", arg1 );
sleep( arg1 );
pthread_mutex_destroy(&(token->mutex));
pthread_cond_destroy(&(token->condition));
printf( "Semaphor deleted.\n" );
printf( "Main thread sleeps 5 sec.\n" );
sleep( 5 );
printf( "Stop.\n" );
return 0;
}
void
thread_proc( void *pParam )
{
int rc;
printf( "\t%s created.\n", pParam );
if (token == (sem_private) NULL)
return ;
if (rc = pthread_mutex_lock(&(token->mutex)))
{
printf( "pthread_mutex_lock ERROR2.\n" );
return ;
}
while (token->semCount <= 0)
{
rc = pthread_cond_wait(&(token->condition), &(token->mutex));
if (rc && errno != EINTR )
break;
}
if( rc )
{
pthread_mutex_unlock(&(token->mutex));
printf( "pthread_mutex_unlock ERROR3.\n" );
return;
}
token->semCount--;
if (rc = pthread_mutex_unlock(&(token->mutex)))
{
printf( "pthread_mutex_lock ERROR.\n" );
return ;
}
printf( "\tSemaphor blocked by %s. (%lx)\n", pParam, rc );
printf( "\t%s sleeps for 5 sec.\n", pParam );
sleep( 5 );
if (rc = pthread_mutex_lock(&(token->mutex)))
{
printf( "pthread_mutex_lock ERROR.\n" );
return ;
}
token->semCount ++;
if (rc = pthread_mutex_unlock(&(token->mutex)))
{
printf( "pthread_mutex_unlock ERROR.\n" );
return ;
}
if (rc = pthread_cond_signal(&(token->condition)))
{
printf( "pthread_cond_signal ERROR.\n" );
return ;
}
printf( "\tSemaphor released by %s. (%lx)\n", pParam, rc );
|

 |

|
進程間信號示例代碼
清單 25. Win32 進程間信號示例代碼,進程 1
#include <stdio.h>
#include <windows.h>
#define WAIT_FOR_ENTER printf( "Press ENTER\n" );getchar()
int main()
{
HANDLE semaphore;
int nRet;
DWORD retVal;
SECURITY_ATTRIBUTES sec_attr;
printf( "Inter Process Semaphore test - Process 1.\n" );
printf( "Start.\n" );
sec_attr.nLength = sizeof( SECURITY_ATTRIBUTES );
sec_attr.lpSecurityDescriptor = NULL;
sec_attr.bInheritHandle = TRUE;
semaphore = CreateSemaphore( &sec_attr, 1, 65536, “456789" );
if( semaphore == (HANDLE) NULL )
return RC_OBJECT_NOT_CREATED;
printf( "Semaphore created. (%lx)\n", nRet );
WAIT_FOR_ENTER;
if( ! ReleaseSemaphore(semaphore, 1, NULL) )
return SEM_POST_ERROR;
printf( "Semaphore Posted. \n");
WAIT_FOR_ENTER;
retVal = WaitForSingleObject (semaphore, INFINITE );
if (retVal == WAIT_FAILED)
return SEM_WAIT_ERROR;
printf( "Wait for Semaphore. \n");
WAIT_FOR_ENTER;
CloseHandle (semaphore);
printf( "Semaphore deleted.\n" );
printf( "Stop.\n" );
return 0;
}
|
清單 26 給出了作為支持進程間共享的有名稱信號示例的消息 IPC 代碼。
清單 26. 相應(yīng)的 Linux 進程間信號示例代碼,進程 1
#include <stdio.h>
#include <sys/types.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#define WAIT_FOR_ENTER printf( "Press ENTER\n" );getchar()
struct msgbuf {
long mtype; /* type of message */
char mtext[1]; /* message text */
};
int main()
{
key_t msgKey;
int flag;
struct msgbuf buff;
int sem;
int nRet =0;
printf( "Inter Process Semaphore test - Process 1.\n" );
printf( "Start.\n" );
flag = IPC_CREAT|IPC_EXCL;
if( ( msgKey = (key_t) atol( "456789" ) ) <= 0 )
return 1;
flag |= S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
sem = (int) msgget( msgKey, flag );
if (sem == -1)
if( errno == EEXIST )
{
flag &= ~IPC_EXCL;
sem = (int) msgget( msgKey, flag );
if (msgctl(sem, IPC_RMID, NULL ) != 0)
return 1;
sem = (int) msgget( msgKey, flag );
if (sem == -1)
return 1;
}
else
return 1;
printf( "Semaphore created. \n" );
WAIT_FOR_ENTER;
buff.mtype = 123;
if( msgsnd( sem, &buff, 1, 0 ) < 0 )
return 1;
printf( "Semaphore Posted. \n" );
WAIT_FOR_ENTER;
if( msgrcv( sem, &buff, 1, 0, 0 ) < 0 )
return 1;
printf( "Wait for Semaphore. \n" );
WAIT_FOR_ENTER;
msgctl(sem, 0, IPC_RMID );
printf( "Semaphore deleted.\n" );
printf( "Stop.\n" );
return 0;
}
|
清單 27. Win32 進程間信號示例代碼,進程 2
#include <stdio.h>
#include <windows.h>
int main()
{
HANDLE semaphore;
DWORD retVal;
printf( "Inter Process Semaphore test - Process 2.\n" );
printf( "Start.\n" );
SECURITY_ATTRIBUTES sec_attr;
sec_attr.nLength = sizeof( SECURITY_ATTRIBUTES );
sec_attr.lpSecurityDescriptor = NULL;
sec_attr.bInheritHandle = TRUE;
semaphore = CreateSemaphore( &sec_attr, 0, 65536, “456789" );
if( semaphore == (HANDLE) NULL )
return RC_OBJECT_NOT_CREATED;
printf( "Semaphore opened. (%lx)\n", nRet );
printf( "Try to wait for semaphore.\n" );
while( ( retVal = WaitForSingleObject( semaphore, 250 ) ) == WAIT_TIMEOUT)
printf( "Timeout. \n");
printf( "Semaphore acquired. \n");
printf( "Try to post the semaphore.\n" );
if( ! ReleaseSemaphore(semaphore, 1, NULL) )
return RC_SEM_POST_ERROR;
printf( "Semaphore posted. \n");
CloseHandle(semaphore);
printf( "Semaphore closed. \n");
printf( "Stop.\n" );
return 0;
}
|
清單 28. 相應(yīng)的 Linux 進程間信號示例代碼,進程 2
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#define RC_TIMEOUT = 3
struct msgbuf {
long mtype; /* type of message */
char mtext[1]; /* message text */
};
int main()
{
key_t msgKey;
int flag=0;
struct msgbuf buff;
int sem;
int nRet =0;
printf( "Inter Process Semaphore test - Process 2.\n" );
printf( "Start.\n" );
if( ( msgKey = (key_t) atol( "456789" ) ) <= 0 )
return 1;
flag |= S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
sem = (int) msgget( msgKey, flag );
if (sem == -1)
if( errno == EEXIST )
{
flag &= ~IPC_EXCL;
sem = (int) msgget( msgKey, flag );
if (msgctl(sem, IPC_RMID, NULL ) != 0)
return 1;
sem = (int) msgget( msgKey, flag );
if (sem == -1)
return 1;
}
else
return 1;
printf( "Semaphore opened. (%lx)\n", nRet );
if( nRet != 0 )
return 0;
printf( "Try to wait for semaphore.\n" );
while( ( nRet = sem_shared_wait_timed( sem, 250 ) ) == 3)
printf( "Timeout. (%lx)\n", nRet );
printf( "Semaphore acquired. (%lx)\n", nRet );
printf( "Try to post the semaphore.\n" );
buff.mtype = 123;
if( msgsnd( sem, &buff, 1, 0 ) < 0 )
return 1;
printf( "Semaphore posted. (%lx)\n", nRet );
if( nRet != 0 )
return 0;
printf( "Semaphore closed. (%lx)\n", nRet );
printf( "Stop.\n" );
return 0;
}
int sem_shared_wait_timed( int sem, unsigned long timelimit)
{
struct msgbuf buff;
struct timeval timeOut;
int msg[1];
int nRet=0;
timeOut.tv_sec = timelimit / 1000;
timeOut.tv_usec = (timelimit % 1000) * 1000;
msg[0] = sem;
nRet = select( 0x1000, (fd_set *)msg, NULL, NULL, &timeOut );
if(nRet == 0)
return 3;
if( msgrcv( sem, &buff, 1, 0, 0 ) < 0 )
return 1;
}
|

 |

|
結(jié)束語
本系列的第三篇文章從信號 API 的角度講述了從 Win32 到 Linux 的映射,并給出了您可以引用的信號示例代碼。線程化的、同步的系統(tǒng)所提出的挑戰(zhàn)不僅是設(shè)計與實現(xiàn),也包括了質(zhì)量保證的所有階段。當(dāng)進行從 Win32 到 Linux 的遷移時,可以將這些文章做為參考。一定要去閱讀本系列中以前的文章。
補充聲明
Microsoft、Windows、Windows NT 和 Windows 徽標(biāo)是 Microsoft Corporation 在美國和/或其他國家或地區(qū)的商標(biāo)或注冊商標(biāo)。
Intel、Intel Inside(logos)、MMX 和 Pentium 是 Intel 公司在美國和/或其他國家或地區(qū)的商標(biāo)。
UNIX 是 The Open Group 在美國和其他國家或地區(qū)的注冊商標(biāo)。
Linux 是 Linus Torvalds 在美國和/或其他國家或地區(qū)的商標(biāo)。
參考資料
關(guān)于作者
 |
|
 |
Nam Keung 是 IBM 的一名高級程序員,他曾致力于 AIX 通信開發(fā)、AIX 多媒體、SOM/DSOM 開發(fā)和 Java 性能方面的工作。他目前的工作包括幫助獨立軟件提供商(Independent Software Vendors,ISV)進行應(yīng)用程序設(shè)計、部署應(yīng)用程序、性能調(diào)優(yōu)和關(guān)于 pSeries 平臺的教育。您可以通過 namkeung@us.ibm.com 與 Nam 聯(lián)系。
|
|