Chinaunix首页 | 论坛 | 博客
  • 博客访问: 71022
  • 博文数量: 25
  • 博客积分: 880
  • 博客等级: 准尉
  • 技术积分: 245
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-05 10:27
文章分类

全部博文(25)

文章存档

2011年(1)

2009年(2)

2008年(22)

我的朋友

分类: LINUX

2008-09-08 16:14:15

转载于

至于什么是信号量(Semaphore),网上相关资料多得很,一搜一大把,我就不做重复劳动了。只是把关于使用信号量的示例程序贴一下当作笔记,万一能对大家有点点帮助那就更好了。 平台的代码来源于 MSDN, 平台的代码是 Google 来的。

Part 1 - Windows 平台信号量(Semaphore)示例程序

#include
#include

#define MAX_SEM_COUNT 10
#define THREADCOUNT 12

HANDLE ghSemaphore;

DWORD WINAPI ThreadProc( LPVOID );

void main(int argc, char* argv[])
{
    HANDLE aThread[THREADCOUNT];
    DWORD ThreadID;
    int i;

    // Create a semaphore with initial and max counts of MAX_SEM_COUNT

    ghSemaphore = CreateSemaphore(
        NULL,           // default security attributes - lpSemaphoreAttributes是信号量的安全属性
        MAX_SEM_COUNT,  // initial count - lInitialCount是初始化的信号量
        MAX_SEM_COUNT,  // maximum count - lMaximumCount是允许信号量增加到最大值
        NULL);          // unnamed semaphore - lpName是信号量的名称

    if (ghSemaphore == NULL)
    {
        printf("CreateSemaphore error: %d\n", GetLastError());
        return;
    }

    // Create worker threads

    for( i=0; i )
    {
        aThread[i] = CreateThread(
            NULL,       // default security attributes
            0,          // default stack size
            (LPTHREAD_START_ROUTINE) ThreadProc,
            NULL,       // no thread function arguments
            0,          // default creation flags
            &ThreadID); // receive thread identifier

        if( aThread[i] == NULL )
        {
            printf("CreateThread error: %d\n", GetLastError());
            return;
        }
    }

    // Wait for all threads to terminate

    WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);

    // Close thread and semaphore handles

    for( i=0; i )
        CloseHandle(aThread[i]);

    CloseHandle(ghSemaphore);
}

DWORD WINAPI ThreadProc( LPVOID lpParam )
{
    DWORD dwWaitResult;
    BOOL bContinue=TRUE;

    while(bContinue)
    {
        // Try to enter the semaphore gate.
        dwWaitResult = WaitForSingleObject(
            ghSemaphore,   // handle to semaphore
            0L);           // zero-second time-out interval

        switch (dwWaitResult)
        {
            // The semaphore object was signaled.
        case WAIT_OBJECT_0:
            // TODO: Perform task
            printf("Thread %d: wait succeeded\n", GetCurrentThreadId());
           
            // Ensure a thread performs only once
            bContinue=FALSE;

            // Simulate thread spending time on task
            Sleep(5);

            // Release the semaphore when task is finished

            if (!ReleaseSemaphore(
                ghSemaphore,  // handle to semaphore - hSemaphore是要增加的信号量句柄
                1,            // increase count by one - lReleaseCount是增加的计数
                NULL) )       // not interested in previous count - lpPreviousCount是增加前的数值返回
            {
                printf("ReleaseSemaphore error: %d\n", GetLastError());
            }
            break;

            // The semaphore was nonsignaled, so a time-out occurred.
        case WAIT_TIMEOUT:
            printf("Thread %d: wait timed out\n", GetCurrentThreadId());
            break;
        }
    }
    return TRUE;
}

Part 2 - Unix 平台信号量(Semaphore)示例程序

/* semabinit.c - initialize a semaphore for use by programs sema and semb */

#include
#include
#include
#include

/* The semaphore key is an arbitrary long integer which serves as an
external identifier by which the semaphore is known to any program
that wishes to use it. */

#define KEY (1492)

void main()
{
int id; /* Number by which the semaphore is known within a program */

/* The next thing is an argument to the semctl() function. Semctl()
does various things to the semaphore depending on which arguments
are passed. We will use it to make sure that the value of the
semaphore is initially 0. */

union semun {
int val;
struct semid_ds *buf;
ushort * array;
} argument;

argument.val = 0;

/* Create the semaphore with external key KEY if it doesn't already
exists. Give permissions to the world. */

id = semget(KEY, 1, 0666 | IPC_CREAT);

/* Always check system returns. */

if(id <0)
{
fprintf(stderr, "Unable to obtain semaphore. ");
exit(0);
}

/* What we actually get is an array of semaphores. The second
argument to semget() was the array dimension - in our case
1. */

/* Set the value of the number 0 semaphore in semaphore array
# id to the value 0. */

if( semctl(id, 0, SETVAL, argument) <0)
{
fprintf( stderr, "Cannot set semaphore value. ");
}
else
{
fprintf(stderr, "Semaphore %d initialized. ", KEY);
}
}

/* Semaphore example program a (sema.c) */
/* We have two programs, sema and semb. Semb may be initiated at any
time, but will be forced to wait until sema is executed. Sema and
semb do not have to be executed by the same user! */

#include
#include
#include
#include

#define KEY (1492)
/* This is the external name by which the semaphore is known to any
program that wishes to Access it. */

void main()
{
int id; /* Internal identifier of the semaphore. */
struct sembuf operations[1];
/* An "array" of one operation to perform on the semaphore. */

int retval; /* Return value from semop() */

/* Get the index for the semaphore with external name KEY. */
id = semget(KEY, 1, 0666);
if(id <0)
/* Semaphore does not exist. */
{
fprintf(stderr, "Program sema cannot find semaphore, exiting. ");
exit(0);
}

/* Do a semaphore V-operation. */
printf("Program sema about to do a V-operation. ");

/* Set up the sembuf structure. */
/* Which semaphore in the semaphore array : */
operations[0].sem_num = 0;
/* Which operation? Add 1 to semaphore value : */
operations[0].sem_op = 1;
/* Set the flag so we will wait : */
operations[0].sem_flg = 0;

/* So do the operation! */
retval = semop(id, operations, 1);

if(retval == 0)
{
printf("Successful V-operation by program sema. ");
}
else
{
printf("sema: V-operation did not succeed. ");
perror("REASON");
}
}

/* Think carefully about what the V-operation does. If sema is executed
twice, then semb can execute twice. */

/* Semaphore example program b (semb.c) */
/* We have two programs, sema and semb. Semb may be initiated at any
time, but will be forced to wait until sema is executed. Sema and
semb do not have to be executed by the same user! */

/* HOW TO TEST:
Execute semb &
The & is important - otherwise you would have have to move to
a different terminal to execute sema.

Then execute sema.
*/

#include
#include
#include
#include

#define KEY (1492)
/* This is the external name by which the semaphore is known to any
program that wishes to access it. */

void main()
{
int id; /* Internal identifier of the semaphore. */
struct sembuf operations[1];
/* An "array" of one operation to perform on the semaphore. */

int retval; /* Return value from semop() */

/* Get the index for the semaphore with external name KEY. */
id = semget(KEY, 1, 0666);
if(id <0)
/* Semaphore does not exist. */
{
fprintf(stderr, "Program semb cannot find semaphore, exiting. ");
exit(0);
}

/* Do a semaphore P-operation. */
printf("Program semb about to do a P-operation. ");
printf("Process id is %d ", getpid());

/* Set up the sembuf structure. */
/* Which semaphore in the semaphore array : */
operations[0].sem_num = 0;
/* Which operation? Subtract 1 from semaphore value : */
operations[0].sem_op = -1;
/* Set the flag so we will wait : */
operations[0].sem_flg = 0;

/* So do the operation! */
retval = semop(id, operations, 1);

if(retval == 0)
{
printf("Successful P-operation by program semb. ");
printf("Process id is %d ", getpid());
}
else
{
printf("semb: P-operation did not succeed. ");
}
}

/* Think carefully about what the V-operation does. If sema is executed
twice, then semb can execute twice. */

阅读(1354) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~