|
程序中用到的 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 标志的进程保存了这么一个变量。 |
|