进程通信-信号
进程通信-信号
//本章学习控制linux进程信号函数,实现通过信号控制进程,使用信号发送信息,学习相关信号操作
//信号操作:1.默认动作 2.改变动作 3.忽略信号 4.阻塞/屏蔽信号
//相关函数:kill/signal/sigqueue/sigaction/sigset_t相关函数/raise/alarm
相关概念
<sys/types.h>
<signal.h>
linux一共62个信号
缺省/默认
kill相关命令/函数
命令
//杀死'单个'进程
kill [option] <pid> [...]
//对'pid'程序发送一个信号
//一般前台程序用ctrl+c终止;后台程序用kill终止
//杀死所有'同名'进程
killall [option] <name> [...]
//对'程序名'程序发送一个信号
//杀掉一类进程/某个用户的所有进程
pkill [OPTIONS] <PATTERN>
//pgrep + kill//pkill只需部分信息
//kill/killall严谨,不完整则报错
//与kill类似,pkill针对的是多个进程,kill针对单个进程
kill:常用命令
kill -sig pid//对'pid'程序发送一个信号
//不同写法
//kill -9 pid
//kill -SIGKILL pid
//kill -KILL pid
kill -l SIGKILL//列出SIGKILL的数值
kill -l//列出所有可用信号
kill 0//终止所有由当前shell启动的进程
killall:常用命令
killall -9 mysql//结束所有mysql进程
pkill:常用命令
pkill -f httpd//查找httpd名的程序,并杀死
pkill -u fghfgh//杀死fgh用户的所有进程//会导致fgh用户退出
函数
<sys/type.h><signal.h>
int kill(pid_t pid,int sig)
//向pid程序发送一个sig
pid//进程标识符//>0 / 0 / -1 / <-1
-> >0:信号发给'pid标志的程序'(常用)
-> 0:信号发给调用进程的'同一组程序'
-> -1:信号发给所有调用进程'有权发送的进程'
-> <-1:信号发给'-pid标志的程序'
sig//准备发送信号代码
常用信号:
-1 SIGHUP 重载
-2 SIGINT 中断 ctrl+c
-3 SIGQUIT 退出 ctrl+\
-9 SIGKILL 杀死进程
-19 SIGSTOP 暂停进程
-18 SIGCONT 继续进程
-14 SIGALRM alarm自动执行信号
signal函数
void (*signal(int sig,void (*func)(int)))(int)
//void (signal)(int)//函数结构
//(int sig,void(func)(int))//函数参数
小知识:不带变量的参数
一般是需要输入,但不使用的函数
工作中,先定接口,再写代码//接口需要稳定,以后可能修改
如果定义了名称不使用,编译会警告//所有用纯类型
//(int)//(int = 2)
用途:
- 改变信号响应//设置执行函数,使用signal关联信号和函数
- 忽略某个信号//signal(sig,SIG_IGN)//ignore
- 恢复默认动作//signal(sig,SIG_DFL)//default
//改变信号响应
//定义信号效果
void fun(int sig){
printf("hello,world\n");
}
//接收SIGNINT信号//执行fun()
signal(SIGINT,fun);
注意事项:
-9/-19 优先级高于用户定义内容/不可修改
sigqueue/sigaction函数
//为了让信号携带信息
int sigqueue(pid_t pid,int sig,const union sigval value)
//kill 升级版本//发送携带额外数据
int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact)
//signal的升级版//接收额外数据
//act使用数据//oldact备份数据(上一个数据)
//use//sigaction
void fun(int sig, siginfo_t *info, void *arg){
printf("sig:%d data:%d\n",sig,info->si_int);
}
struct sigaction m_action;
m_action.sa_handler=fun;
m_action.sa_flags=0;
sigacton(sig,)
//相关参数
//sigqueue///const union sigval value
union sigval{
int sival_int;//保存发送整数
void *sival_ptr;//保存发送地址
};
//sigaction//const struct sigaction *act
struct sigaction {
void (*sa_handler)(int);//存放执行函数//兼容signal
void (*sa_sigaction)(int, siginfo_t *, void *);//与sigaction配合使用
sigset_t sa_mask;
int sa_flags;//0->与以前signal兼容//1->与现在sigqueue配合使用
void (*sa_restorer)(void);
};
//siginfo_t
The siginfo_t argument to sa_sigaction is a struct with the following fields:
siginfo_t {
int si_signo; /* Signal number 信号编号 */
int si_errno; /* An errno value 如果为非零值则错误代码与之关联 */
int si_code; /* Signal code 说明进程如何接收信号以及从何处收到*/
int si_trapno; /* Trap number that caused
hardware-generated signal
(unused on most architectures) */
pid_t si_pid; /* Sending process ID适用于SIGCHLD,代表被终止进程的PID */
uid_t si_uid; /* Real user ID of sending process适用于SIGCHLD,代表被终止进程所拥有进程的UID */
int si_status; /* Exit value or signal 适用于SIGCHLD,代表被终止进程的状态 */
clock_t si_utime; /* User time consumed 适用于SIGCHLD,代表被终止进程所消耗的用户时间 */
clock_t si_stime; /* System time consumed 适用于SIGCHLD,代表被终止进程所消耗系统的时间 */
==================
sigval_t si_value; /* Signal value */
==================
int si_int; /* POSIX.1b signal */
void *si_ptr; /* POSIX.1b signal */
int si_overrun; /* Timer overrun count;
POSIX.1b timers */
int si_timerid; /* Timer ID; POSIX.1b timers */
void *si_addr; /* Memory location which caused fault */
long si_band; /* Band event (was int in
glibc 2.3.2 and earlier) */
int si_fd; /* File descriptor */
short si_addr_lsb; /* Least significant bit of address
(since Linux 2.6.32) */
void *si_call_addr; /* Address of system call instruction
(since Linux 3.5) */
int si_syscall; /* Number of attempted system call
(since Linux 3.5) */
unsigned int si_arch; /* Architecture of attempted system call
(since Linux 3.5) */
}
等待信号 pause()函数
int pause(void)
//阻塞等待,直到收到一个信号,往下运行
阻塞/屏蔽信号 sigset_t类型使用
sigset_t类型的变量(本质上是一个数组/存放多个信号)->linux又称:信号阻塞源码集
int sigemptyset(sigset_t *set); //清空集合
int sigfillset(sigset_t *set); //加62个//把linux中62个信号一起添加到set集合中
int sigaddset(sigset_t *set, int signum); //加一个//把signum信号添加到set集合中
int sigdelset(sigset_t *set, int signum); //把signum信号从集合中剔除
int sigismember(const sigset_t *set, int signum); //判断signum在不在set
//设置信号阻塞
int sigprocmask(int how, const sigset_t *set,sigset_t *oset)
how -> //怎么使用//控制
SIG_BLOCK //设置信号阻塞,把set和oset两个集合中的所有信号都阻塞
SIG_SETMASK //设置信号阻塞,只阻塞set这个集合中的所有信号
SIG_UNBLOCK //解除信号阻塞
set ->//使用集合//保存你想要阻塞的所有信号
oset ->//备份集合//保存之前你设置的阻塞信号
//例:
sigset_t m_set,old_set;//定义信号变量集合
sigemptyset(&m_set);//清空
sigaddset(&m_set,SIGINT)//加入信号,SIGINT
sigaddset(&m_set,SIGQUIT)//加入信号,SIGQUIT
sigprocmask(SIG_BLOCK,&m_set,&old_set)//对m_set和old_set内的信号进行信号阻塞
//old_set//之前设置的信号屏蔽集合
现象:
kill -SIGINT PID//没反应(被屏蔽了),还在等待信号
if//kill -4 PID//反映了,退出
if//sigprocmask(SIG_UNBLOCK,&m_set,&old_set)
//反应,退出//被屏蔽信号进来了,退出进程
其他信号函数
//自己给自己信号
int raise(int sig)
//等价于kill(getpid(),int sig)
//定时器,间隔多少秒,发送SIGALRM信号
unsigned alarm(unsigned seconds)
//比sleep()好//期间可以执行别的,sleep()只能傻等
例:
signal(SIGALRM,fun);
alarm(5);//间隔5秒钟,alarm自动发送SIGALRM信号
pause();
void fun(int sig){
printf("alarm使用了\n");
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!