IO进、线程——进程间通信的信号通信:kill()、raise()、alarm()、pause()、signal()

信号通信

1. 介绍

信号是进程间通信中一种简单而有效的机制,用于通知进程发生了某个事件。当某个进程产生一个信号时,它可以向其他进程发送信号,并触发接收进程的信号处理函数。信号机制可以用于进程之间的异步通信,比如在一个进程执行的过程中,另一个进程可以通过发送信号来中断或修改其执行行为。

信号是内核进程通知用户进程应该干什么了

2. 信号的基本概念

2.1 信号的产生和处理

信号是由操作系统或其他进程发送给目标进程的通知,可以表示某种事件的发生,如按下Ctrl+C键、子进程终止等。进程可以设置信号处理函数来对收到的信号做出响应,处理函数可以是用户自定义的函数。

2.2 信号的类型

信号是用整数表示的,不同的信号有不同的整数值。例如,SIGINT代表终止进程的信号,其整数值为2。Linux系统中有许多不同的信号,每个信号都有特定的含义和用途。

信号名 编号 信号名 编号 信号名 编号
SIGHUP 1 SIGRTMIN 34 SIGRTMAX-9 55
SIGINT 2 SIGRTMIN+1 35 SIGRTMAX-8 56
SIGQUIT 3 SIGRTMIN+2 36 SIGRTMAX-7 57
SIGILL 4 SIGRTMIN+3 37 SIGRTMAX-6 58
SIGTRAP 5 SIGRTMIN+4 38 SIGRTMAX-5 59
SIGABRT 6 SIGRTMIN+5 39 SIGRTMAX-4 60
SIGBUS 7 SIGRTMIN+6 40 SIGRTMAX-3 61
SIGFPE 8 SIGRTMIN+7 41 SIGRTMAX-2 62
SIGKILL 9 SIGRTMIN+8 42 SIGRTMAX-1 63
SIGUSR1 10 SIGRTMIN+9 43 SIGRTMAX 64
SIGSEGV 11 SIGRTMIN+10 44
SIGUSR2 12 SIGRTMIN+11 45
SIGPIPE 13 SIGRTMIN+12 46
SIGALRM 14 SIGRTMIN+13 47
SIGTERM 15 SIGRTMIN+14 48
SIGSTKFLT 16 SIGRTMIN+15 49
SIGCHLD 17 SIGRTMAX-14 50
SIGCONT 18 SIGRTMAX-13 51
SIGSTOP 19 SIGRTMAX-12 52
SIGTSTP 20
SIGTTIN 21
SIGTTOU 22
SIGURG 23
SIGXCPU 24
SIGXFSZ 25
SIGVTALRM 26
SIGPROF 27
SIGWINCH 28
SIGIO 29
SIGPWR 30
SIGSYS 31

2.3 发送信号

发送信号的操作通常由操作系统或其他进程执行。发送信号的常用方法是使用kill命令或系统调用kill()。
①kill():

#include 

int kill(pid_t pid, int sig);

功能:往指定进程发送信号
返回值:成功返回0,失败返回-1
参数说明:
pid:向哪个进程发送信号

-1:所有进程(不能用)
0:表示发送信号给指定进程ID的进程。

sig:具体的某个信号(信号类型)

②raise():

int raise(int sig);

功能:向进程自己发送信号
返回值:成功返回0,失败返回非0
sig:要发送的信号
raise(SIGINT); // <==> kill(getpid(), SIGINT);

#include 
#include 
#include 

void sig_handler(int signum){
    if(signum == SIGINT){
        printf("收到信号CTRL+C:%d\n",signum);
    }
    if(signum == SIGQUIT){
        printf("收到信号CTRL+\\:%d\n",signum);
    }
}
int main(int argc, char *argv[])
{ 
    int sig1 = SIGINT;
    int sig2 = SIGQUIT;
    //绑定信号
    signal(sig1, sig_handler);
    signal(sig2, sig_handler);
    //自己给自己发信号
    raise(sig1);
    raise(sig2);
    while(1);

    return 0;
} 
~                  

③alarm():

unsigned int alarm(unsigned int seconds);

功能:开启定时器进行计时,时间到了产生SIGALRM信号
返回值:上一次定时过后还剩多少秒,如果是第一次定时返回0
seconds:要定时多久,写0表示取消定时

#include 
#include 
int main(int argc, char *argv[])
{ 
    int ret = alarm(10);
    printf("开始计时10秒\n");
    printf("上一次还剩下ret 1 = %d 秒\n", ret);

    sleep(3);
    printf("延迟了三秒\n");

    ret = alarm(3);
    printf("上一次还剩下ret 2 = %d 秒\n",ret);

    while(1);

    return 0;
} 

④pause():

int pause(void);

功能:暂定进程,需要收到信号才能继续执行

#include 
#include 
#include 

void sig_handler(int signum){
    printf("接收到信号 CTRL+C :%d\n",signum);
}

int main(int argc, char *argv[])
{ 
    int sig = SIGINT;
    signal(sig, sig_handler);
    printf("进程暂停,等待信号……\n");
    pause();
    printf("进程恢复。\n");

    return 0;
} 

3. 信号处理

3.1 设置信号处理函数

进程可以使用系统调用signal()来设置信号处理函数,其原型如下:

#include 

void (*signal(int signum, void (*handler)(int)))(int);

或者是下面的

typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

功能:绑定信号与某个操作
参数说明:
signum:是要设置处理函数的信号编号
handler:是指向信号处理函数的处理方式。

SIG_IGN:忽略信号
SIG_DFL:默认操作
或者自定义函数,指定信号发生时需要执行的操作。

信号处理函数的定义如下:

void handler(int signum);

信号处理函数接收一个整数参数signum,它是收到的信号的编号。在信号处理函数中,可以对接收到的信号做出相应的处理,如终止进程、忽略信号等。

3.2 默认信号处理行为

对于每个信号,操作系统都有一个默认的信号处理行为。例如,SIGINT信号的默认处理行为是终止进程,而SIGCHLD信号的默认处理行为是忽略。进程可以通过设置信号处理函数来改变默认的处理行为。

信号名 含义 默认操作
SIGABRT 中止进程,如调用abort()函数 终止进程
SIGALRM 定时器超时 终止进程
SIGBUS 非法地址访问(总线错误) 终止进程
SIGCHLD 子进程状态改变 忽略
SIGCONT 继续运行停止的进程 忽略
SIGFPE 浮点异常(如除以零) 终止进程
SIGHUP 终端断开 终止进程
SIGILL 非法指令 终止进程
SIGINT 终端中断(如按下Ctrl+C) 终止进程
SIGKILL 杀死进程 终止进程
SIGPIPE 管道破裂(写入一个没有读取端) 终止进程
SIGQUIT 终端退出(如按下Ctrl+\) 终止进程
SIGSEGV 无效的内存引用 终止进程
SIGSTOP 停止进程 停止进程
SIGTERM 终止信号(如kill命令) 终止进程
SIGTSTP 终端挂起(如按下Ctrl+Z) 停止进程
SIGTTIN 后台进程读终端 停止进程
SIGTTOU 后台进程写终端 停止进程
SIGUSR1 用户自定义信号1 终止进程
SIGUSR2 用户自定义信号2 终止进程
SIGPOLL I/O事件发生 终止进程
SIGPROF 进程运行时间超过时钟周期 终止进程
SIGSYS 非法系统调用 终止进程
SIGTRAP 跟踪/断点发生 终止进程
SIGURG 紧急数据到达套接字 忽略
SIGVTALRM 虚拟定时器超时 终止进程
SIGXCPU 进程超过CPU时限 终止进程
SIGXFSZ 文件大小超过限制 终止进程
SIGWINCH 窗口大小发生改变 忽略
SIG_BLOCK 阻塞指定的信号
SIG_UNBLOCK 解除对指定信号的阻塞
SIG_SETMASK 设置阻塞信号的掩码

3.3 信号屏蔽

有时候,我们不希望在某段代码执行期间被某些信号中断。可以使用系统调用sigprocmask()来设置信号屏蔽,从而阻塞某些信号的传递。被屏蔽的信号会在sigprocmask()被调用后暂时被阻塞,直到解除屏蔽为止。

你可能感兴趣的:(IO进,线程,linux,运维,服务器,c语言)