Linux学习(19):信号量-2

1.信号集的定义

 信号集是由位图机制实现的

位图机制是一种数据结构,用于存储和操作大量位(即二进制数)的集合。在计算机科学中,它通常被用于表示布尔值或标志,并且可以有效地压缩空间。

位图由一组按顺序排列的比特(0或1)组成,并使用一个或多个字节来存储。每个比特位置都对应着某些状态、属性或标记,例如“是否启用”、“是否已读取”等等。因此,在许多情况下,我们可以将这些信息编码为单个整数并将其保存在一个数组中。

 未决信号集和阻塞信号集

未决信号集(Pending Signal Set)是指正在等待被处理的信号的集合。当一个进程收到一个信号时,该信号会被添加到该进程的未决信号集中,并且只有在进程处理完当前正在进行的操作后才能处理这个未决信号。
阻塞信号集(Blocked Signal Set)则是指一组已经阻塞或者暂停了对应于这些特定类型的信号处理程序执行过程中接受新消息或通知请求的操作系统内部数据结构。

1.用户通过键盘  Ctrl + C, 产生2号信号SIGINT (信号被创建)

2.信号产生但是没有被处理 (未决状态)
    - 在内核中将所有的没有被处理的信号存储在一个集合中 (未决信号集)
    - SIGINT信号状态被存储在第二个标志位上
        - 这个标志位的值为0, 说明信号不是未决状态
        - 这个标志位的值为1, 说明信号处于未决状态(此时为1)
    
3.这个未决状态的信号,需要被处理,处理之前需要和另一个信号集(阻塞信号集),进行比较
    - 阻塞信号集默认不阻塞任何的信号
    - 如果想要阻塞某些信号需要用户调用系统的API

4.在处理的时候和阻塞信号集中的标志位进行查询,看是不是对该信号设置阻塞了
    - 如果没有阻塞(0),这个信号就被处理
    - 如果阻塞了(1),这个信号就继续处于未决状态,直到阻塞解除,这个信号就被处理

 信号集相关的函数

//前五个可以设置自己定义的信号集
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set,int signum);
int sigdelset(sigset_t *set,int signum);
int sigismember(const sigset_t *set,int signum);

//后面两个可以处理系统内核的信号集
int sigprocmask(int how,const sigset_t *set,sigset_t *oldset);
int sigpending(sigset_t *set);

2.处理自定义信号集的一些函数

2.1 sigemptyset函数

功能:清空信号集中的数据,将信号集中的所有的标志位置为0

    int sigemptyset(sigset_t *set);
        - 参数:set,传出参数,需要操作的信号集
        - 返回值:成功返回0, 失败返回-1

2.2 sigfillset函数

功能:将信号集中的所有的标志位置为1

    int sigfillset(sigset_t *set);
        - 参数:set,传出参数,需要操作的信号集
        - 返回值:成功返回0, 失败返回-1

2.3 sigaddset函数

设置信号集中的某一个信号对应的标志位为1,表示阻塞这个信号

    int sigaddset(sigset_t *set, int signum);
        - 参数:
            - set:传出参数,需要操作的信号集
            - signum:需要设置阻塞的那个信号
        - 返回值:成功返回0, 失败返回-1

2.4 sigdelset函数

功能:设置信号集中的某一个信号对应的标志位为0,表示不阻塞这个信号

    int sigdelset(sigset_t *set, int signum);
        - 参数:
            - set:传出参数,需要操作的信号集
            - signum:需要设置不阻塞的那个信号
        - 返回值:成功返回0, 失败返回-1

2.5 sigismember函数

 功能:判断某个信号是否阻塞,因为不需要改变信号集,参数类型为const

    int sigismember(const sigset_t *set, int signum);
        - 参数:
            - set:需要操作的信号集
            - signum:需要判断的那个信号
        - 返回值:
            1 : signum被阻塞
            0 : signum不阻塞
            -1 : 失败

测试代码

#include <signal.h>
#include <stdio.h>

int main() {

    // 创建一个信号集,传出参数
    sigset_t set;

    // 可能有默认值,清空信号集的内容
    sigemptyset(&set);

    // 判断 SIGINT 是否在信号集 set 里,此时不阻塞
    int ret = sigismember(&set, SIGINT);
    if(ret == 0) {
        printf("SIGINT 不阻塞\n");
    } else if(ret == 1) {
        printf("SIGINT 阻塞\n");
    }

    // 添加信号到信号集中
    sigaddset(&set, SIGINT);

    // 判断SIGINT是否在信号集中,此时阻塞
    ret = sigismember(&set, SIGINT);
    if(ret == 0) {
        printf("SIGINT 不阻塞\n");
    } else if(ret == 1) {
        printf("SIGINT 阻塞\n");
    }

    // 从信号集中删除信号
    sigdelset(&set, SIGINT);

    // 判断SIGINT是否在信号集中,此时又不阻塞了
    ret = sigismember(&set, SIGINT);
    if(ret == 0) {
        printf("SIGINT 不阻塞\n");
    } else if(ret == 1) {
        printf("SIGINT 阻塞\n");
    }

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux 中,可以使用 `semctl` 系统调用中的 `GETVAL` 命令来获取指定信号量的值。如果该值为0,则表示信号量已经被占用,没有可用的资源。 具体的代码实现可以参考如下示例: ```c #include <stdio.h> #include <stdlib.h> #include <sys/sem.h> int main() { int semid; struct sembuf sb; // 创建信号量集 semid = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT); if (semid == -1) { perror("semget"); exit(EXIT_FAILURE); } // 初始化信号量 if (semctl(semid, 0, SETVAL, 1) == -1) { perror("semctl"); exit(EXIT_FAILURE); } // 获取信号量的值 printf("Sem value: %d\n", semctl(semid, 0, GETVAL)); // 尝试获取信号量 sb.sem_num = 0; sb.sem_op = -1; // P 操作 sb.sem_flg = SEM_UNDO; if (semop(semid, &sb, 1) == -1) { perror("semop"); exit(EXIT_FAILURE); } printf("Semaphore acquired\n"); // 释放信号量 sb.sem_op = 1; // V 操作 if (semop(semid, &sb, 1) == -1) { perror("semop"); exit(EXIT_FAILURE); } printf("Semaphore released\n"); // 删除信号量集 if (semctl(semid, 0, IPC_RMID, 0) == -1) { perror("semctl"); exit(EXIT_FAILURE); } return 0; } ``` 在这个示例中,我们首先使用 `semget` 系统调用创建了一个信号量集,并使用 `semctl` 系统调用对该信号量进行了初始化。然后使用 `semctl` 系统调用获取了该信号量的值,并输出到控制台。 接下来,我们使用 `semop` 系统调用进行了一次 P 操作,即尝试获取该信号量。如果该信号量的值为0,则该操作将会被阻塞,直到信号量的值变为非0。在本例中,由于我们已经将信号量初始化为1,因此该 P 操作可以顺利完成。 最后,我们使用 `semop` 系统调用进行了一次 V 操作,即释放该信号量。然后使用 `semctl` 系统调用删除了该信号量集。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值