Linux信号阻塞与未达

信号在内核中的表示

执行信号的处理动作称为信号递达(Delivery),信号从产生到递达之间的状态,称为信号未决(Pending)。进程可以选择阻塞(Block)某个信号。被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。

注意,阻塞和忽略是不同,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。信号在内核中的表示可以看作是这样的:

@font-face {
font-family: "Times New Roman";
}@font-face {
font-family: "宋体";
}@font-face {
font-family: "Tahoma";
}@font-face {
font-family: "Symbol";
}@font-face {
font-family: "Arial";
}@font-face {
font-family: "黑体";
}@font-face {
font-family: "Courier New";
}@font-face {
font-family: "Wingdings";
}@font-face {
font-family: "微软雅黑";
}@font-face {
font-family: "Calibri";
}@font-face {
font-family: "Cambria";
}@font-face {
font-family: "Sans Serif";
}@font-face {
font-family: "方正书宋_GBK";
}p.p0 { margin: 0pt; text-align: justify; font-size: 10.5pt; font-family: ‘Calibri‘; }div.Section0 { page: Section0; }

说明:

1)PCB进程控制块中函数有信号屏蔽状态字(block)和信号未决状态字(pending)还有是否忽略标志;

2)信号屏蔽状态字(block),1代表阻塞、0代表不阻塞;信号未决状态字(pending)的1代表未决,0代表信号可以抵达了;

3)向进程发送SIGINT,内核首先判断信号屏蔽状态字是否阻塞,若阻塞,信号未决状态字(pending)相应位制成1;若阻塞解除,信号未决状态字(pending)相应位制成0;表示信号可以抵达了。

4)block状态字、pending状态字 64位(bit);

5)block状态字用户可以读写,pending状态字用户只能读;这是信号设计机制。

思考1:状态字都64bit,编程时,如何表示状态字那?

思考2:block状态字信息如何获取或者操作那?哪些api?

思考3:pending状态字信息如何获取或者操作那?哪些api?

答案见下;

信号集操作函数(状态字表示)

sigpending获取信号未决状态字(pending)信息

#include <signal.h>
int sigemptyset(sigset_t *set);	//把信号集清零;(64bit/8=8字节)
int sigfillset(sigset_t *set); 	//把信号集64bit全部置为1
int sigaddset(sigset_t *set, int signo); 	//根据signo,把信号集中的对应位置成1
int sigdelset(sigset_t *set, int signo); 	//根据signo,把信号集中的对应位置成0
int sigismember(const sigset_t *set, int signo);	//判断signo是否在信号集中

sigprocmask读取/更改信号屏蔽状态字(Block)

int sigprocmask(int how, const sigset_t *set, sigset_t *oset);

功能:读取或更改进程的信号屏蔽字。

返回值:若成功则为0,若出错则为-1

读取:如果oset是非空指针,则读取进程的当前信号屏蔽字通过oset参数传出。

更改:如果set是非空指针,则更改进程的信号屏蔽字,参数how指示如何更改。如果oset和set都是非空指针,则先将原来的信号屏蔽字备份到oset里,然后根据set和how参数更改信号屏蔽字。假设当前的信号屏蔽字为mask,下表说明了how参数的可选值。

How:

 
NAME
       sigpending - examine pending signals
SYNOPSIS
       #include <signal.h>
       int sigpending(sigset_t *set);
DESCRIPTION
       sigpending()  returns the set of signals that are pending for delivery to the calling thread (i.e., the signals which have been raised while blocked).  The mask of pending signals is returned in set.

信号阻塞未达实践

void printSignalPending(sigset_t *printSigSet)
{
    for (unsigned i = 1; i < NSIG; ++i)
    {
        if (sigismember(printSigSet,i))
        {
            putchar(‘1‘);
        }
        else
        {
            putchar(‘0‘);
        }
    }
    putchar(‘\n‘);
}

void onSignalAction(int signalNumber)
{
    switch(signalNumber)
    {
    case SIGINT:
        cout << "SIGINT = " << signalNumber << endl;
        cout << "I have return .... ^^ ^^ ^^ ^^" << endl;
        break;
    case SIGQUIT:
        cout << "SIGQUIT = " << signalNumber << endl;

        //对SIGINT信号解除阻塞
        cout << "Unblock SIGINT..." << endl;
        sigset_t unblockSigset;
        sigemptyset(&unblockSigset);
        sigaddset(&unblockSigset,SIGINT);
        sigprocmask(SIG_UNBLOCK,&unblockSigset,NULL);
        break;
    default:
        cout << "Other Signal ..." << endl;
        break;
    }
}

int main()
{
    if (signal(SIGINT,onSignalAction)== SIG_ERR)
    {
        perror("signal error");
        return -1;
    }
    if (signal(SIGQUIT,onSignalAction) == SIG_ERR)
    {
        perror("signal error");
        return -1;
    }

    sigset_t setSigSet,printSigSet;
    sigemptyset(&setSigSet);
    sigaddset(&setSigSet,SIGINT);   //添加SIGINT到信号屏蔽字
    //sigaddset(&setSigSet,SIGQUIT);  //添加SIGQUIT到信号屏蔽字

	//更改进程的信号屏蔽字 这里用来阻塞Ctrl+c[SIGINT]信号
	//SIGINT信号被设置成阻塞,即使用户按下Ctrl+c键盘,也不会抵达
    sigprocmask(SIG_BLOCK,&setSigSet,NULL);

    while (true)
    {
        //获取并打印未决字信息
        sigpending(&printSigSet);
        printSignalPending(&printSigSet);

        sleep(2);
    }

    return 0;
}

/**
    连续的按Ctrl+c键盘,虽然发送了多个SIGINT信号,
    但是因为信号是不稳定的(不支持排队),所以只保留了一个,如下图
*/

附-杀死改进程,需要另启一终端,执行

killall main

附-Makefile文件

CC = g++
CPPFLAGS = -Wall -g

BIN = main
SOURCES = $(wildcard *.cpp)
OBJECTS = $(SOURCES:.cpp=.o)

.PHONY: clean all 

all: $(BIN)

$(BIN): $(OBJECTS)

%.o: %.cpp
    $(CC) $(CPPFLAGS) -o [email protected] -c $<

clean:
    -rm -rf $(BIN) $(OBJECTS)
时间: 2024-12-08 16:22:23

Linux信号阻塞与未达的相关文章

[学习笔记]信号的阻塞和未达

信号在内核中的表示 q  执行信号的处理动作称为信号递达(Delivery),信号从产生到递达之间的状态,称为信号未决(Pending).进程可以选择阻塞(Block)某个信号.被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作. q  注意,阻塞和忽略是不同,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作.信号在内核中的表示可以看作是这样的: 说明1)PCB进程控制块中结构体中有信号屏蔽状态字(block),信号未决状态字(pending)还有是否

LINUX信号

一.产生信号的三种方式: 1.由键盘(终端按键)产生,比如在shell下启动一个前台进程(控制台下的进程),按Ctrl^C(只能发给前台进程)会产生一个硬件中断,若CPU正在执行此进程代码,则该进程用户空间代码暂停执行,CPU从用户态切换到内核态处理中断,如果不是自定义信号处理函数,一般默认的处理动作为终止进程,所以在内核态直接终止进程而不返回用户区. 2.由系统函数发送信号,可用kill命令给某个指定进程发送信号,它是调用kill函数实现的. 模型:kill -发送几号信号 给哪个进程 例:k

LINUX 信号概念详解

LINUX 信号概念详解 我们运行如下命令,可看到Linux支持的信号列表: # kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD 18) SIGCONT 19) SIGSTOP

Linux信号列表

我们运行如下命令,可看到Linux支持的信号列表:~$ kill -l1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR213) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) S

Linux信号(signal) 机制分析

[摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核对于信号的处理流程包括信号的触发/注册/执行及注销等.最后介绍了应用层的相关处理,主要包括信号处理函数的安装.信号的发送.屏蔽阻塞等,最后给了几个简单的应用实例. [关键字]软中断信号,signal,sigaction,kill,sigqueue,settimer,sigmask,sigprocmask,sigset_t 1       信

Linux 信号理解(二)

linux下信号基本概念见:Linux 信号理解(一) 接下来讲重点讲述信号捕捉设定 #include<stdio.h> #include<signal.h> #include<errno.h> void capture_sig(int num) { int n=4; printf("capture_sig is called \n"); while(n--) { sleep(1); printf(" num:%d \n",num

linux信号-------初涉

一.信号的本质 软中断信号(signal,又简称为信号)用来通知进程发生了异步事件.在软件层次上是对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的.信号是进程间通信机制中唯一的异步通信机制,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达.进程之间可以互相通过系统调用kill发送软中断信号.内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件.信号机制除了基本通知功能外,还可以传递附加信息 二.信号的分类 1)

Linux 信号:signal 与 sigaction

0.Linux下查看支持的信号列表: [email protected]:~$ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCON

linux信号调用机制

在Linux中,信号是进程间通讯的一种方式,它采用的是异步机制.当信号发送到某个进程中时,操作系统会中断该进程的正常流程,并进入相应的信号处理函数执行操作,完成后再回到中断的地方继续执行. 需要说明的是,信号只是用于通知进程发生了某个事件,除了信号本身的信息之外,并不具备传递用户数据的功能. 1 信号的响应动作 每个信号都有自己的响应动作,当接收到信号时,进程会根据信号的响应动作执行相应的操作,信号的响应动作有以下几种: 中止进程(Term) 忽略信号(Ign) 中止进程并保存内存信息(Core