zoukankan      html  css  js  c++  java
  • 分配和释放信号量

    与用于分配、释放共享内存的shmget和shmctl类似,系统调用semget和semctl
    负责分配、释放信号量。调用semget函数并传递如下参数:一个用于标识信号量组的键值,
    该组中包含的信号量数量和与shmget所需的相同的权限位标识。该函数返回的是信号量组
    的标识符。你可以通过指定正确的键值来获取一个已经存在的信号量的标识符;这种情况下,
    传递的信号量组的容量可以为0
    信号量会一直保存在系统中,甚至所有使用它们的进程都退出后也不会自动被销毁。最
    后一个使用信号量的进程必须明确地删除所使用的信号量组,来确保系统中不会有太多闲置
    的信号量组,从而导致无法创建新的信号量组。可以通过调用semctl来删除信号量组。调
    用时的四个参数分别为信号量组的标识符,组中包含的信号量数量、常量 IPC_RMID 和一
    个union semun类型的任意值(被忽略)。调用进程的有效用户id必须与分配这个信号量
    组的用户id相同(或者调用进程为root权限亦可)。与共享内存不同,删除一个信号量组
    会导致Linux立即释放资源。
    列表5.2 展示了用于分配和释放一个二元信号量的函数。
    代码列表5.2 (sem_all_deall.c)分配和释放二元信号量
    #include <sys/ipc.h>
    #include <sys/sem.h>
    #include <sys/types.h>
    /* 我们必须自己定义semun 联合类型。*/
    union semun {
    int val;
    struct semid_ds *buf;
    unsigned short int *array;
    struct seminfo *__buf;
    };
    /* 获取一个二元信号量的标识符。如果需要则创建这个信号量*/
    int binary_semaphore_allocation (key_t key, int sem_flags)
    {
    return semget (key, 1, sem_flags);
    }
    /* 释放二元信号量。所有用户必须已经结束使用这个信号量。如果失败,返回-1 */
    int binary_semaphore_deallocate (int semid)
    {
    union semun ignored_argument;
    return semctl (semid, 1, IPC_RMID, ignored_argument);
    }

    5.2.3 等待和投递操作
    每个信号量都具有一个非负的值,且信号量支持等待和投递操作。系统调用semop实
    现了这两个操作。它的第一个参数是信号量的标识符,第二个参数是一个包含struct
    sembuf类型元素的数组;这些元素指明了你希望执行的操作。第三个参数是这个数组的长
    度。
    结构体sembuf中包含如下字段:
    · sem_num将要执行操作的信号量组中包含的信号量数量

    · sem_op是一个指定了操作类型的整数

    · 如果sem_op是一个正整数,则这个值会立刻被加到信号量的值上
    如果sem_op为负,则将从信号量值中减去它的绝对值如果这将使信号量的值小
    于零,则这个操作会导致进程阻塞,直到信号量的值至少等于操作值的绝对值(由
    其它进程增加它的值)。
    · 如果sem_op为0,这个操作会导致进程阻塞,直到信号量的值为零才恢复。
    · sem_flg  是一个符号位。指定  IPC_NOWAIT  以防止操作阻塞;如果该操作本应
    阻塞,则semop调用会失败。如果为sem_flg指定SEM_UNDO,Linux会在进
    程退出的时候自动撤销该次操作。
    列表5.4 展示了二元信号量的等待和投递操作。
    代码列表5.4 (sem_pv.c)二元信号量的等待和投递操作
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/sem.h>
    /* 等待一个二元信号量。阻塞直到信号量的值为正,然后将其减1 */
    int binary_semaphore_wait (int semid)
    {
    struct sembuf operations[1];
    /* 使用(且仅使用)第一个信号量*/
    operations[0].sem_num = 0;
    /* 减一*/
    operations[0].sem_op = -1;
    /* 允许撤销操作*/
    operations[0].sem_flg = SEM_UNDO;
    return semop (semid, operations, 1);
    }
    /* 对一个二元信号量执行投递操作:将其值加一。
    这个操作会立即返回。*/
    int binary_semaphore_post (int semid)
    {
    struct sembuf operations[1];
    /* 使用(且仅使用)第一个信号量*/
    operations[0].sem_num = 0;
    /* 加一*/
    operations[0].sem_op = 1;
    /* 允许撤销操作*/
    operations[0].sem_flg = SEM_UNDO;

    return semop (semid, operations, 1);
    }

    指定SEM_UNDO标志解决当出现一个进程仍然持有信号量资源时被终止这种特殊情
    况时可能出现的资源泄漏问题。当一个进程被有意识或者无意识地结束的时候,信号量的值
    会被调整到“撤销”了所有该进程执行过的操作后的状态。例如,如果一个进程在被杀死之
    前减小了一个信号量的值,则该信号量的值会增长。---?????

    5.2.4 调试信号量
    命令ipcs -s可以显示系统中现有的信号量组的相关信息。而ipcrm sem命令可以
    从命令行删除一个信号量组。例如,要删除标识符为5790517的信号量组则应运行以下命令:
    % ipcrm sem 5790517

  • 相关阅读:
    继承与钻石继承
    面向对象----对象的组合和
    认知类和对象的关系
    初识面向对象----类和对象的关系
    其他题目
    三级菜单
    用户登陆
    购物车题目
    函数练习题目
    类加载的过程
  • 原文地址:https://www.cnblogs.com/michile/p/2908215.html
Copyright © 2011-2022 走看看