| 
 | 
 
程序中用到的 semget() , semop() ,semctl() 函数: 
http://www.groad.net/bbs/read.ph ... ;    (semget) 
http://www.groad.net/bbs/read.ph ... ;    (semop ) 
http://www.groad.net/bbs/read.ph ... ;    (semctl ) 
 
测试代码: 
 #include <unistd.h> 
 #include <stdlib.h> 
 #include <stdio.h> 
 #include <sys/types.h> 
 #include <linux/sem.h> 
  
 static int set_semvalue (void); 
 static void del_semvalue (void); 
 static int semaphore_p (void); 
 static int semaphore_v (void); 
  
 static int sem_id; 
  
 int main (int argc, char *argv[]) 
 { 
     int i; 
     int pause_time; 
     char op_char = 'O'; 
  
     srand ((unsigned int)getpid ()); 
      
     sem_id = semget ((key_t)1234, 1, 0666 | IPC_CREAT); 
  
     if (argc > 1) { 
         if (!set_semvalue()) { 
             fprintf (stderr, "Failed to initialize semaphpre\n"); 
             exit (EXIT_FAILURE); 
         } 
         op_char = 'X'; 
         sleep (5); 
     } 
      
     for (i = 0; i < 10; i++) { 
         if (!semaphore_p ()) exit (EXIT_FAILURE); 
         printf ("%c", op_char);  
         fflush (stdout); 
  
         pause_time = rand () % 3; 
         printf ("%c", op_char); 
         fflush (stdout); 
  
         if (!semaphore_v()) exit (EXIT_FAILURE); 
  
         pause_time = rand() % 2; 
         sleep (pause_time); 
     } 
     printf ("\n%d - finished\n", getpid()); 
  
     if (argc > 1) { 
         sleep (10); 
         del_semvalue (); 
     } 
      
     exit (EXIT_SUCCESS); 
 }     
  
 static int set_semvalue (void) 
 { 
     union semun sem_union; 
      
     sem_union.val = 1; 
     if (semctl (sem_id, 0, SETVAL, sem_union) == -1) return (0); 
         return (1); 
 } 
  
 static void del_semvalue (void) 
 { 
     union semun sem_union; 
          
     if (semctl (sem_id, 0, IPC_RMID, sem_union) == -1) 
         fprintf (stderr, "Failed to delete semaphore\n"); 
 } 
  
  
 static int semaphore_p (void) 
 { 
     struct sembuf sem_b; 
  
     sem_b.sem_num = 0; 
     sem_b.sem_op = -1; 
     sem_b.sem_flg = SEM_UNDO; 
      
     if (semop (sem_id, &sem_b, 1) == -1) { 
         fprintf (stderr, "semaphore_p failed\n"); 
         return (0); 
     } 
     return (1); 
 } 
  
 static int semaphore_v (void) 
 { 
     struct sembuf sem_b; 
      
     sem_b.sem_num = 0; 
     sem_b.sem_op = 1; 
     sem_b.sem_flg = SEM_UNDO; 
      
     if (semop (sem_id, &sem_b, 1) == -1) { 
         fprintf (stderr, "semaphore_v failed\n"); 
         return (0); 
     } 
     return (1); 
 }  测试运行及输出:beyes@linux-beyes:~/C/sem> ./sem.exe 1 & 
[1] 9179 
beyes@linux-beyes:~/C/sem> ./sem.exe 
OOXXOOOOXXOOOOXXOOXXXXXXXXXXXXXX 
9179 - finished 
OOOOOOOO 
9182 - finished  说明: 
第一次先用带有参数 1 的方式在后台运行了 sem.exe ,很快的,再运行不带参数的 sem.exe 。此后,两个程序会不断交替地试图获取信号量并输出相应的字符(带参数的程序输出 X,不带的输出 O),然后释放信号量。 
 
创建成功后的信号量,是内核在维护的,是一个全局性的东西,被创建的信号量对于两个程序来说都是可见的。 
 
在 sembuf 结构体中,第一个参数 sem_num 表示指定要在信号量集中对哪个信号量进行操作。它的值通常会设为 0 ;但是如果工作在多个信号量上,这个值也可以是其它大于 0 的整数。 
 
sem_op 的值如果 < 0,那么对应的操作是 P 操作,也就是,申请信号量,当信号量的值(semun 联合体中的 val )变为大于或等于sem_op 的绝对值之前,如果没有设置 IPC_NOWAIT ,则调用程序被迫等待。 
 
如果信号量的值 大于或等于 sem_op ,则从信号量的值中减去 sem_op 的绝对值。并且,如果在 sem_flg 中设置了 SEM_UNDO 标志 , sem_op 的绝对值就会被加到指定信号量的调用进程里的信号量调节值中。这样,如果调用进程意外终止时,系统就会撤销该进程的信号量操作,这个调节值就会被加回信号量中去。实际上,内核为每个在信号量操作中指定了 SEM_UNDO 标志的进程保存了这么一个变量。 |   
 
 
 
 |