曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 5749|回复: 0
打印 上一主题 下一主题

信号量应用实例

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
跳转到指定楼层
楼主
发表于 2009-9-5 12:13:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
程序中用到的 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 标志的进程保存了这么一个变量。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-5-4 23:39 , Processed in 0.096850 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表