【Linux】进程信号_3

发布于:2024-06-30 ⋅ 阅读:(15) ⋅ 点赞:(0)


八、进程信号

2. 信号的保存

实际执行信号的处理动作称为信号递达(Delivery)
信号从产生到递达之间的状态,称为信号未决(Pending)。
进程可以选择阻塞 (Block )某个信号。
被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。
注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。

在进程的PCB中,有两个位图,一个是判断是否收到相应信号的位图pending,一个是决定该位置的信号是否阻塞的位图block。
在这里插入图片描述
handler表是一组函数指针,决定信号的执行方法。
调用函数 sigprocmask 可以读取或更改进程的信号屏蔽字(阻塞信号集)。
在这里插入图片描述

int main()
{
    // 创建阻塞信号集
    sigset_t block, oblock;
    
    // 清空信号集
    sigemptyset(&block);
    sigemptyset(&oblock);

    // 将2号信号添加进阻塞信号集
    sigaddset(&block, 2);
	
	// 将阻塞信号集设置到内核中
    int n = sigprocmask(SIG_SETMASK, &block, &oblock);
    assert(n == 0);

    while (true)
    {
        // 创建pending信号集
        sigset_t pending;
        sigemptyset(&pending);

        // 获取pending信号集
        n = sigpending(&pending);
        assert(n == 0);

        // 打印pending信号集
        PrintSig(pending);
        sleep(1);
    }

    return 0;
}

在这里插入图片描述
9号信号、19号信号无法被屏蔽,18号信号会做特殊处理。操作系统不允许出现 金刚不坏 的进程。
如何解除屏蔽?

	while (true)
    {
        int cnt = 0;
        // 创建pending信号集
        sigset_t pending;
        sigemptyset(&pending);

        // 获取pending信号集
        n = sigpending(&pending);
        assert(n == 0);

        // 打印pending信号集
        PrintSig(pending);
        ++cnt;
        if (cnt == 20)
        {
            // 解除阻塞信号集
            n = sigprocmask(SIG_UNBLOCK, &block, &oblock);
            assert(n == 0);
        }
        sleep(1);
    }

3. 信号的处理


未完待续