现在的位置: 首页 > 综合 > 正文

The Summery of Linux Semaphore

2013年12月06日 ⁄ 综合 ⁄ 共 4487字 ⁄ 字号 评论关闭

A semaphore is nothing more than a variable that is protected. It provides a means to restrict access to a resource that is shared amongst two or more processes. Two operations are permitted, commonly called acquire and release. The acquire operation allows a process to take the semaphore, and if it has already been acquired, then the process blocks until it’s available. If a process has the semaphore, it can release it, which allows other processes to acquire it. The process of releasing a semaphore automatically wakes up the next process awaiting it on the acquire operation.

The Type of Semaphore
 
The binary semaphore represents a single resource, and therefore when one process has acquired it, others are blocked until it is released.
The counting semaphore is used to represent shared resources in quantities greater than one.
 
The Head Files and Linux APIs:
  
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget( key_t key, int nsems, int semflg );
int semop( int semid, struct sembuf *sops, unsigned int nsops );
int semctl( int semid, int semnum, int cmd, ... );
  
User Utilities
   
GNU/Linux provides the ipcs command to explore semaphores from the command line.
# ipcs –s 
This presents all the semaphores that are visible to the calling process.
# ipcs -s -i semid
We can get extended information about the semaphore using the -i option.
    
Creating a Semaphore
   
#include <stdio.h>
#include <sys/sem.h>
#include <stdlib.h>
int main()
{
    int semid;
   
    /* Create the semaphore with the id MY_SEM_ID */
    semid = semget( MY_SEM_ID, 1, 0666 | IPC_CREAT );
 
    if (semid >= 0)
       printf( "semcreate: Created a semaphore %d/n", semid );
 
    return 0;
}
        
Getting a Semaphore
        
#include <stdio.h>
#include <sys/sem.h>
#include <stdlib.h>
int main()
{
    int semid;
    struct sembuf sb;
 
    /* Get the semaphore with the id MY_SEM_ID */
    semid = semget( MY_SEM_ID, 1, 0 );
    if (semid >= 0)
    {
       sb.sem_num = 0;
       sb.sem_op = -1;
       sb.sem_flg = 0;
       printf( "semacq: Attempting to acquire semaphore %d/n", semid );
       /* Acquire the semaphore */
       if ( semop( semid, &sb, 1 ) == -1 )
       {
           printf( "semacq: semop failed./n" );
           exit(-1);
       }
       printf( "semacq: Semaphore acquired %d/n", semid );
    }
    return 0;
}
       
Releasing a Semaphore
          
#include <stdio.h>
#include <sys/sem.h>
#include <stdlib.h>
int main()
{
    int semid;
    struct sembuf sb;
 
    /* Get the semaphore with the id MY_SEM_ID */
    semid = semget( MY_SEM_ID, 1, 0 );
    if (semid >= 0)
    {
       printf( "semrel: Releasing semaphore %d/n", semid );
       sb.sem_num = 0;
       sb.sem_op = 1;
       sb.sem_flg = 0;
   
       /* Release the semaphore */
       if (semop( semid, &sb, 1 ) == -1)
       {
           printf("semrel: semop failed./n");
           exit(-1);
       }
      
       printf( "semrel: Semaphore released %d/n", semid );
    }
    return 0;
}
  
Retrieving the Current Semaphore Count
      
int main()
{
    int semid, cnt;
 
    /* Get the semaphore with the id MY_SEM_ID */
    semid = semget( MY_SEM_ID, 1, 0 );
    if (semid >= 0)
    {
       /* Read the current semaphore count */
       cnt = semctl( semid, 0, GETVAL );
       if (cnt != -1)
           printf("semcrd: current semaphore count %d./n", cnt);
    }
    return 0;
}
            
Setting the Current Semaphore Count
         
#include <stdio.h>
#include <sys/sem.h>
#include <stdlib.h>
int main()
{
    /* Get the semaphore with the id MY_SEM_ID */
    int semid = semget( MY_SEM_ID, 1, 0 );
   
    if (semid >= 0)
    {
       /* Set the current semaphore count */
       ret = semctl( semid, 0, SETVAL, 6 );
       if (ret != -1)
           printf( "semcrd: semaphore count updated./n" );
    }
    return 0;
}
           
Removing a Semaphore
          
#include <stdio.h>
#include <sys/sem.h>
#include <stdlib.h>
int main()
{
    /* Get the semaphore with the id MY_SEM_ID */
    int semid = semget( MY_SEM_ID, 1, 0 );
   
    if (semid >= 0)
    {
       int ret = semctl( semid, 0, IPC_RMID);
       if (ret != -1)
           printf( "Semaphore %d removed./n", semid );
    }
    return 0;
}
        
 

Another Example
         
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>
 
int main()
{
    int semid = semget( 0x33333, 1, 0666|IPC_CREAT );
    if( semid >= 0)
        printf("sem 33 created: %d/n", semid);
 
    sembuf sb;
 
    int ret = fork();
    if( ret == 0 ) ////child process:
    {
       printf("child 1 active/n");
       //get sem:
       //sembuf sb;
       int semid1 = semget( 0x33333, 1, 0);
       if( semid1 >= 0 )
       {
           printf("attempt to acquire sem %d/n", semid1 );
           sb.sem_num = 0;
           sb.sem_op = -1;
           sb.sem_flg = 0;
           if( semop( semid , &sb, 1 ) == -1 )
               printf( "semop error in child process/n");
           // we have the sem:
           printf("child 1 get the sem/n");
       }
       exit(0);
    }
 
 
    // main process:
    printf( "main process release sem/n" );
    sb.sem_num = 0;
    sb.sem_op = 1;
    sb.sem_flg = 0;
    semop( semid , &sb, 1 );
 
    printf("main process exit/n");
    return 0;
}
   

抱歉!评论已关闭.