`
cuiyadll
  • 浏览: 201303 次
文章分类
社区版块
存档分类
最新评论

将 Win32 C/C++ 应用程序迁移到 POWER 上的 Linux,第 3 部分: 信号

阅读更多

 

http://blog.csdn.net/j6915819/article/details/17220029

信号

信号是包含有一个正数的资源。信号允许进程通过一个单一的原子操作来测试和设置那个整数的值,以此实现同步。通常,信号的主要用途是同步某个线程与其他线程的动作。在多个进程竞争访问同一操作系统资源时,这也是协调或者同步那些行为的一种实用技术。

Linux 支持 Portable Operating System Interface(POSIX)信号以及 pthread 条件变量,以此来映射 Win32 信号 API。它们各有其优缺点。您应该基于应用程序的逻辑来判断使用哪种方法。在映射事件信号的过程中需要考虑的方面包括:

  • 信号的类型:Win32 既支持有名称的事件信号,也支持无名称的事件信号。有名称的信号是在多个进程间共享的。Linux 不支持这种方案。本文中列出的一个进程间通信(Inter-Process Communication,IPC)消息队列示例代码将向您展示如何来解决此问题。
  • 初始状态:在 Win32 中,信号可能会有初始值。在 Linux 中,POSIX 信号支持此功能,但 pthreads 不支持。在使用 pthreads 时您需要考虑到这一点。
  • 超时:Win32 事件信号支持定时等待。在 Linux 中,POSIX 信号实现只支持不确定的等待(阻塞)。pthreads 实现既支持阻塞也支持超时。pthread_cond_timedwait() 调用能给出等待期间的超时的值,pthread_cond_wait() 则用于不确定的等待。
  • 发信号:在 Win32 中,发出信号会唤醒等待那个信号的所有线程。在 Linux 中,POSIX 线程实现一次只唤醒一个线程。pthreads 实现的 pthread_cond_signal() 调用会唤醒一个线程,pthread_cond_broadcast() 调用会向所有等待那个信号的线程发出信号。

表 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
 

条件变量

条件变量让开发者能够实现一个条件,在这个条件下线程执行然后被阻塞。Microsoft® Win32 接口本身不支持条件变量。为解决此缺憾,我使用 POSIX 条件变量模拟同步原语,并在一系列文章中对此进行了概述。在 Linux 中,它可以确保因某条件被阻塞的线程,当那个条件改变时,会被解除阻塞。它还允许您原子地(atomically)解除互斥的锁定,并等待条件变量,而不 会有干涉其他线程的可能。不过,每个条件变量都应该伴有一个互斥。前面的表 1 给出了用于线程间同步的 pthread 条件变量。

 

创建信号

在 Win32 中,CreateSemaphore 函数可以创建一个有名称的或者无名称的信号对象。Linux 不支持有名称的信号。


清单 1. 创建信号
HANDLE CreateSemaphore (
	LPSECURITY_ATTRIBUTES	lpSemaphoreAttributes,
	LONG			lInitialCount,
	LONG			lMaximunCount,
	LPCTSTR			lpName
); 

在 Linux 中,sem_init() 调用会创建一个 POSIX 信号:


清单 2. POSIX 信号
                    
int sem_init(sem_t *sem, int pshared, unsigned int value

Linux 使用 pthread_condition_init 调用在当前进程内创建信号对象,在其中维持一个在零与最大值之间的计数值。每次有某个线程完成对信号的等待,这个计数值会减小,而每次当某个线程释放这个信号时,计数值增加。当计数值成为零时,信号对象的状态成为 non-signaled。


清单 3. 创建信号对象的 pthread_condition_init 调用
                    
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. 相应的 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 所创建的信号对象。


清单 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 代码和相应的 Linux 代码
Win32 代码 相应的 Linux 代码
CloseHandle(semHandle); pthread_mutex_destroy(&(token->mutex));

pthread_cond_destroy(&(token->condition));

free (token);
 

发布事件信号

在 Win32 中,ReleaseSemaphore 函数会令指定的信号对象的计数值增加指定数量。


清单 10. ReleaseSemaphore 函数
                    
BOOL ReleaseSemaphore(
	HANDLE hSemaphore,
	LONG 	lReleaseCount,
	LPLONG	lpPreviousCount
);

Linux POSIX 信号使用 sem_post() 来发布事件信号。这将唤醒阻塞于此信号的所有线程。


清单 11. sem_post() 
                    
int sem_post(sem_t * sem);

在 Linux 中,pthread_cond_signal 会唤醒等待某个条件变更的某个线程。Linux 调用这个函数来为此对象所标识的信号发布一个事件完成信号。调用的线程增加那个信号的值。如果信号的值从零开始增加,而且 pthread_cond 中有任何线程被阻塞,那么请等待这个信号,因为其中一个会被唤醒。默认情况下,实现可以选择任意的正在等待的线程。


清单 12. pthread_cond_signal 
                    
int pthread_cond_signal(pthread_cond_t *cond);


清单 13. Win32 代码和相应的 Linux 代码
Win32 代码 相应的 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 调用 WaitForSingleObject 函数来等待所需要的信号上事件的完成。当等待单一线程同步对象时,可以使用此方法。当对象被设置发出信号或者超时时间段结束时,这个方法会得到通知。如果时间间隔是 INFINITE,那么它就会无止境地等待下去。


清单 14. WaitForSingleObject 函数
                    
DWORD WaitForSingleObject(
	HANDLE hHANDLE,
	DWORD	dwMilliseconds
);

使用 WaitForMultipleObjects 函数来等待多个被通知的对象。在信号线程同步对象中,当计数器变为零时,对象是 non-signaled。


清单 15. WaitForMultipleObjects 函数
                    
DWORD WaitForMultipleObjects(
	DWORD	nCount,
	Const	HANDLE* lpHandles,
	BOOL	bWaitAll,
	DWORD	dwMilliseconds
);

Linux POSIX 信号使用 sem_wait() 来挂起发出调用的线程,直到信号拥有了非零的计数值。然后它自动地减少信号的计数值。


清单 16. sem_wait() 函数
                    
int sem_wait(sem_t * sem);

在 POSIX 信号中不能使用超时选项。不过,您可以通过在某个循环中执行非阻塞的 sem_trywait() 来完成此功能,它会计算超时的值。


清单 17. sem_trywait() 函数
                    
int sem_trywait(sem_t  * sem);

在 Linux 中,pthread_cond_wait() 会阻塞发出调用的线程。发出调用的线程会减小那个信号。如果当 pthread_cond_wait 被调用时信号是零,则 pthread_cond_wait() 就会阻塞,直到另一个线程增加了那个信号的值。


清单 18. pthread_cond_wait() 函数
                    
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t  *mutex);

pthread_cond_wait 函数首先释放相关联的 external_mutex of type pthread_mutex_t,当调用者检查条件表达式时必须持有它。


清单 19. Win32 代码和相应的 Linux 代码
Win32 代码 相应的 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;

如果您需要在指定的一段时间内阻塞发出调用的线程,那么请使用 pthread_cond_timewait 来阻塞它。调用这个方法来等待所需要信号上某个事件的完成,等待指定的一段时间。


清单 20. pthread_cond_timewait
                
	int pthread_cond_timewait(
	pthread_cond_t		*cond,
	pthread_mutex_t		*mutex,
	timespec		*tm
);			




清单 21. Win32 代码和相应的 Linux 代码
Win32 代码 相应的 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 信号来实现线程 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);

 

进程内信号示例代码


清单 23. Win32 进程内信号示例代码
                
#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. 相应的 Linux 进程内信号示例代码
                
#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. 相应的 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. 相应的 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;
}

 

结束语

本系列的第三篇文章从信号 API 的角度讲述了从 Win32 到 Linux 的映射,并给出了您可以引用的信号示例代码。线程化的、同步的系统所提出的挑战不仅是设计与实现,也包括了质量保证的所有阶段。当进行从 Win32 到 Linux 的迁移时,可以将这些文章做为参考。一定要去阅读本系列中以前的文章。

分享到:
评论

相关推荐

    Win32 C/C++编写的斗地主游戏程序源码

    Win32 C/C++编写的斗地主游戏程序源码,包括服务器与客户端程序,VS2005开发。 支持服务器定制(添加、删除、编辑所选服务器参数), 支持游戏大厅功能,支持常规的斗地主游戏及旁观功能,支持基本聊天功能。

    WIN32/C/C++贪吃蛇

    这个项目展示了如何在Windows平台上利用Win32 API来创建一个图形用户界面(GUI)应用程序。尽管它是在VS2008下编写的,但该代码应能在更高版本的Visual Studio中无缝运行,因为Microsoft一直保持着向后兼容性。 ...

    精通Matlab与C/C++混合程序设计(第三版) 配套光盘

    《精通Matlab与C/C++混合程序设计》第三版是一本深入探讨如何将两种强大的编程语言结合使用的专业书籍。在当今的科学计算和工程应用中,Matlab以其强大的数学计算能力受到广泛欢迎,而C/C++则以其高效、灵活和广泛的...

    C/C++程序设计学习与实验系统

    原名《Turbo C/C++ for Windows 集成实验与学习环境》,支持最新操作系统WINDOWS 7,它是从事一线教学的大学教师根据C/C++ 初学者的特点,量身定制的一个简单易用的 C/C++程序设计学习与实验软件(支持TC2/TC3、VC6三...

    mysql-6.1.11-win32 C/C++ 连接驱动

    这个版本的C/C++连接驱动允许开发者使用C或C++编程语言直接与MySQL数据库进行交互,为应用程序提供数据存储和检索功能。在描述中提到,它也是Qt最新版本中编译MySQL驱动所必需的库文件,因为Qt官方不再随发行版附带...

    用 VISUAL C++ 设计WIN32应用程序.rar

    《用Visual C++设计Win32应用程序》是一个深入探讨如何使用Microsoft Visual C++开发Windows桌面应用程序的教程。这个教程可能是由网上某个知名资源站点提供的原版资料,旨在帮助程序员理解和掌握Win32 API编程。 ...

    Microtec C/C++ Compiler Toolkit For PowerPC

    ### Microtec C/C++ Compiler Toolkit for PowerPC:深入解析与应用 #### 概述 Microtec C/C++ Compiler Toolkit for PowerPC(版本3.4)是专为嵌入式开发人员设计的一套全面且高效的交叉编译解决方案。该工具集...

    Eclipse IDE for C/C++ Win32位

    Eclipse IDE for C/C++是专为C/C++开发者设计的一款强大的集成开发环境(IDE),尤其在Windows 32位操作系统上表现出色。Eclipse作为一个开源项目,它提供了丰富的功能和高度可扩展性,使得软件开发变得更加高效和...

    c/c++完整视频教程(三)——–Linux服务器编程

    根据提供的文件信息,本篇文章将围绕“C/C++完整视频教程(三)——Linux服务器编程”这一主题展开,深入解析该教程所涵盖的关键知识点。由于实际视频内容无法直接获取,以下解析将基于标题、描述及标签提供的信息...

    win32 程序移植到linux上

    文章中还提到了IBM的技术专家,如Nam Keung和Chakarat Skawratananond,他们在帮助开发者将应用程序移植到IBM pSeries平台上的AIX5L和Linux方面有丰富的经验。这些专家的存在对于那些希望通过移植在IBM Bluemix云...

    实现往linux上应用程序迁移的报告

    【标题】:“实现往Linux上应用程序迁移的报告” 【描述】:应用程序的迁移涉及系统间的兼容性问题,包括系统与应用程序的相互适应性。在Linux系统中,迁移不仅仅是确保应用程序能够运行,还需要全面测试其与Linux...

    Win32 API 与C/C++标准库函数

    《Win32 API 与C/C++标准库函数》是一个针对Windows平台编程的重要参考资料,它包含两个主要部分:Windows API的全面指南以及C/C++标准库的参考手册。这两个部分对于任何想要深入理解和开发Windows系统应用程序的...

    linux c/c++基础学习资料(百度云链接和提取码)

    在Linux上开发C/C++程序,需要安装必要的开发工具,如GCC/G++编译器、Make工具、GDB调试器等。同时,理解环境变量、编译链接过程、动态库静态库的使用也是编程环境搭建的关键。此外,学会使用版本控制系统如Git进行...

    C/C++ 定时器程序(含源码和demo)

    本资源提供了一个C/C++实现的定时器程序,包含源码和demo,支持在Windows和Linux上跨平台运行,这为我们提供了深入理解定时器机制和跨平台编程的一个实践案例。 首先,C++定时器的实现方式多种多样,常见的有以下几...

    C/C++编译器 LCC-WIN32

    LCC-WIN32是一款专为Windows 32位操作系统设计的小型C/C++编译器,它以其轻量级的特性而受到许多初学者和经验丰富的开发者的欢迎。这款编译器的主要特点在于它的体积小巧,使得在有限的系统资源下也能高效地运行和...

    c/c++嵌入式开发与linux命令大全

    4. **可移植性**:C语言编写的应用程序可以在不同的平台上编译运行,具有良好的可移植性。 C++是在C语言基础上扩展的,增加了类和面向对象编程(OOP)的概念,使得代码更加模块化和可重用。C++的特点包括: 1. **...

    NI采集卡 linux下C/C++语言demo

    标题 "NI采集卡 Linux下C/C++语言demo" 涉及到的是使用National Instruments(NI)的DAQmx(数据采集和测量系统)驱动在Linux操作系统中进行数据采集的编程实践。NI采集卡是一种用于实验测量和控制的硬件设备,能够...

    语言编LINUX下KTron的游戏.rar_C/C++ 街机游戏_C语言 Linux_linux c++ 游戏_游戏_街机

    标题中的“语言编LINUX下KTron的游戏.rar”表明这是一个在Linux操作系统下用C/C++编程语言开发的街机风格的游戏项目。这个项目可能是基于KTron,一个类似于经典电子游戏Tron的小型赛车游戏。KTron利用C或C++的编程...

    c/c++复制字符串到剪粘板中

    C/C++复制字符串到剪粘板中是指将字符串复制到剪粘板中,以便在其他应用程序中使用。这可以通过Win32 API和MFC来实现。 在Win32 API中,可以使用OpenClipboard、GetClipboardData、GlobalLock、GlobalUnlock、...

Global site tag (gtag.js) - Google Analytics