当前位置: 首页 > news >正文

Linux进程5-进程通信常见的几种方式、信号概述及分类、kill函数及命令、语法介绍

目录

1.进程间通信概述

1.1进程通信的主要方式

1.2进程通信的核心对比

2.信号

2.1 信号的概述

2.1.1 信号的概念

2.2信号的核心特性

2.3信号的产生来源

2.4信号的处理流程

2.5关键系统调用与函数

2.6常见信号的分类及说明

2.6.1. 标准信号(Standard Signals)

2.6.2. 实时信号(Real-Time Signals)

2.6.3. 不可捕获/忽略的信号

2.6.4. 用户自定义信号

2.6.5. 调试与跟踪信号

2.6.6. 终端与作业控制信号

2.6.7. 系统与资源信号

2.7信号分类总结

3.kill函数

3.1 kill命令终端执行

3.1.1基本语法

3.1.1.1. 终止进程

3.1.1.2. 暂停与恢复进程

3.1.1.3. 自定义操作

3.1.1.4. 批量终止进程

3.1.2 kill终端运行程序


1.进程间通信概述

进程间通信(IPC:Inter Processes Communication), 进程是一个独立的资源分配单元,不同进程(这里所说的进程通常指的是用户进程)之 间的资源是独立的,没有关联,不能在一个进程中直接访问另一个进程的资源(例如打开的 文件描述符)。 进程不是孤立的,不同的进程需要进行信息的交互和状态的传递等,因此需要进程间通信。
进程通信的核心目标:
  • 数据传输:进程间交换数据(如管道、套接字)。
  • 资源共享:多个进程共享同一资源(如共享内存、文件)。
  • 协调同步:控制进程执行顺序(如信号量、互斥锁)。
  • 事件通知:异步告知进程某事件发生(如信号)。

1.1进程通信的主要方式

根据通信原理和适用场景,IPC 可分为以下类别:

1. 基于文件的通信

  • 普通文件:多个进程读写同一文件(需同步机制)。
  • 内存映射文件(mmap):将文件映射到内存,多进程直接访问同一内存区域
  • 命名管道(FIFO):通过文件系统路径标识的管道,无关进程可通过路径名通信。

2. 基于内核的通信

  • 匿名管道(Pipe):父子进程间的单向通信,通过 | 或 pipe() 创建。
  • 消息队列(Message Queue):内核维护的链表结构,支持结构化消息(类型、优先级)。
  • 共享内存(Shared Memory):多个进程映射同一物理内存区域,速度最快,但需同步机制(如信号量)。
  • 信号量(Semaphore):控制对共享资源的访问,解决竞态条件(如 System V 或 POSIX 信号量)。
  • 信号(Signal):内核向进程发送异步事件通知(如 SIGTERM 终止进程)。

3. 基于网络的通信

  • 套接字(Socket)支持跨网络或本地进程通信(如 TCP/UDP 套接字、Unix 域套接字)。

4. 其他高级机制

  • RPC(远程过程调用):跨进程/机器的函数调用抽象。
  • DBus:Linux 桌面环境中的高级消息总线,用于进程间服务调用。

1.2进程通信的核心对比

机制方向数据量同步需求适用场景
匿名管道单向父子进程简单通信
命名管道单向无关进程顺序通信
消息队列双向结构化消息传递(异步)
共享内存双向必需高性能数据共享(需同步)
信号单向异步进程控制(如终止、挂起)
信号量无数据同步资源访问互斥
套接字双向可选跨网络/本地可靠通信
1.3进程间通信的实质:
系统只要创建一个进程,就会给当前进程分配4G的虚拟内存(32位操作系统),虚拟内存不是常说的内存条的空间,内存条的空间称之为物理内存,虚拟内存和物理内存之间存在映射关系。
4G的虚拟内存分为3G的用户空间(0~3G)和1G(3~4G)的内核空间 用户空间是进程所私有 的, 每一个进程的用户空间只能自己访问和使用 ,我们之前说的栈 区、堆区、数据区、代码区等都是用户空间的区域,内核空间是所有进程所公有的,也就意味着绝大多数进程间通信方式,本质就是对内核空间 的操作。

2.信号

2.1 信号的概述

2.1.1 信号的概念

 信号(Signal) 是操作系统内核向进程发送的异步事件通知机制,用于通知进程发生了特定事件(如用户中断、程序错误等)。它是进程间通信(IPC)中最轻量级的方式之一,常用于进程控制、错误处理和简单事件通知。

信号是软件中断 它是在软件层次上对中断机制的一种模拟。 信号可以导致一个正在运行的进程被另一个正在运行的异步进程中断,转而处理某一个突发事件。
信号可以 直接进行用户空间进程和内核空间进程的交互 ,内核进程可以利用它来通知用户空间进程发生了哪些系统事件。
每个信号的名字都以字符SIG开头。
每个信号和一个数字编码相对应,在头文件signum.h中,这些信号都被定义为正整数。
信号名定义路径:
终端输入:sudo find /usr/include -name "signum.h" 命令,查看signum.h的位置
signum.h中的信号:
在Linux下,要想查看这些信号和编码的对应关系,可使用命令: kill ­-l

2.2信号的核心特性

  1. 异步性:信号可能在任何时间点到达进程,打断其正常执行流程。
  2. 有限信息:仅传递信号编号(如 SIGINT),无法携带额外数据。
  3. 预定义类型:Linux 定义了一些标准信号(1~31 和 34~64),如:
    • SIGINT (2):终端中断(Ctrl+C)。
    • SIGKILL (9):强制终止进程(不可捕获或忽略)。
    • SIGSEGV (11):非法内存访问(段错误)。
    • SIGTERM (15):请求进程正常终止(优雅终止进程)。
    • SIGUSR1 (10) 和 SIGUSR2 (12):用户自定义信号。
  4. 处理方式:进程可选择忽略、捕获(执行处理函数)或执行默认操作。

2.3信号的产生来源

来源示例场景
用户输入终端按下 Ctrl+C(发送 SIGINT)。
内核事件进程访问非法内存(触发 SIGSEGV)、子进程终止(发送 SIGCHLD)。
其他进程通过 kill() 或 kill 命令发送信号(如 kill -9 PID 发送 SIGKILL)。
程序自身调用 raise() 或 abort() 触发信号(如 SIGABRT)。

2.4信号的处理流程

  1. 信号产生:由内核、用户或其他进程触发。
  2. 信号递送:内核将信号放入目标进程的待处理信号队列
  3. 信号处理:进程在用户态内核态切换时检查待处理信号,并根据注册的处理方式响应:
    • 默认行为(如终止、暂停、忽略)。
    • 捕获信号:执行用户自定义的信号处理函数。
    • 忽略信号SIGKILL 和 SIGSTOP 除外)。

2.5关键系统调用与函数

  1. 发送信号
    • kill(pid, sig):向指定进程发送信号。
    • raise(sig):向当前进程发送信号。
    • sigqueue(pid, sig, value):发送信号并附带额外数据(需配合 sigaction 使用)。
  2. 处理信号
    • signal(sig, handler):简单注册信号处理函数(不推荐,可能不可靠)。
    • sigaction(sig, act, oldact):更安全的信号处理配置(推荐使用)。
  3. 阻塞信号
    • sigprocmask():屏蔽或解除屏蔽信号,防止处理函数被中断。
  4. 等待信号
    • pause():挂起进程直到收到信号。
    • sigsuspend():临时修改信号掩码并等待信号。

2.6常见信号的分类及说明

2.6.1. 标准信号(Standard Signals)

编号范围:1~31(即 SIGRTMIN 之前的信号),这些是传统的 UNIX 信号,功能固定。

核心分类

类型信号默认行为典型触发场景
进程终止SIGTERM (15)终止进程kill 默认发送,允许优雅退出
SIGKILL (9)立即终止进程kill -9 强制终止,不可捕获或忽略
SIGQUIT (3)终止并生成 core 文件终端按下 Ctrl+\
用户交互SIGINT (2)终止进程终端按下 Ctrl+C
SIGTSTP (20)暂停进程(可恢复)终端按下 Ctrl+Z
程序错误SIGSEGV (11)终止并生成 core 文件非法内存访问(段错误)
SIGFPE (8)终止并生成 core 文件算术错误(如除零)
SIGILL (4)终止并生成 core 文件非法指令(如执行损坏的二进制文件)
进程控制SIGCHLD (17)忽略子进程终止或状态变化
SIGCONT (18)恢复进程运行用于恢复被暂停的进程(如 fg 命令)
SIGSTOP (19)立即暂停进程不可捕获或忽略,用于作业控制

2.6.2. 实时信号(Real-Time Signals)

编号范围:34~64(即 SIGRTMIN 到 SIGRTMAX),支持队列化携带附加数据

  • 特点
    • 可排队:同一信号多次发送不会丢失(标准信号可能合并为一次)。
    • 可携带数据:通过 sigqueue() 发送时附加 sival_int 或 sival_ptr
  • 用途:高可靠性事件通知(如自定义通信)。

2.6.3. 不可捕获/忽略的信号

  • SIGKILL (9) 和 SIGSTOP (19):
    • 内核直接处理,进程无法修改其行为(无法捕获或忽略)
    • 用于强制终止(SIGKILL)或立即暂停(SIGSTOP)进程。

2.6.4. 用户自定义信号

  • SIGUSR1 (10) 和 SIGUSR2 (12):
    • 默认行为是终止进程,但通常由程序重定义为自定义逻辑(如重载配置、触发备份)。
    • 示例:

      bash

      # 发送 SIGUSR1 到进程 1234
      kill -USR1 1234
      

2.6.5. 调试与跟踪信号

信号默认行为用途
SIGTRAP (5)终止并生成 core 文件调试断点触发(如 gdb 单步执行)
SIGABRT (6)终止并生成 core 文件程序调用 abort() 主动终止(断言失败)

2.6.6. 终端与作业控制信号

信号默认行为触发场景
SIGHUP (1)终止进程终端断开连接(常用于通知守护进程重载配置)
SIGWINCH (28)忽略终端窗口大小改变(如 vim 动态调整界面)

2.6.7. 系统与资源信号

信号默认行为触发场景
SIGPIPE (13)终止进程写入无读端的管道(如 `管道
SIGALRM (14)终止进程定时器到期(alarm() 或 setitimer()
SIGXCPU (24)终止进程进程超出 CPU 时间限制
SIGXFSZ (25)终止进程文件大小超出限制

2.7信号分类总结

分类代表信号核心用途
进程终止SIGTERMSIGKILLSIGQUIT终止或强制终止进程
用户交互SIGINTSIGTSTP终端控制(暂停/终止)
程序错误SIGSEGVSIGFPESIGILL处理非法操作或崩溃
进程控制SIGCHLDSIGCONTSIGSTOP管理子进程或作业控制
实时通信SIGRTMIN~SIGRTMAX高可靠性事件通知(支持队列化和数据携带)
调试与资源SIGTRAPSIGXCPUSIGALRM调试、资源超限或定时任务

3.kill函数

函数原型:

#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int signum);功能:
给指定进程发送信号。参数:
pid:详见下页
signum:信号的编号返回值:
成功返回 0,失败返回 -1。pid 的取值有 4 种情况:
pid>0: 将信号传送给进程 ID 为 pid 的进程。
pid=0: 将信号传送给当前进程所在进程组中的所有进程。
pid=-1: 将信号传送给系统内所有的进程。
pid<-1: 将信号传给指定进程组的所有进程。这个进程组号等于 pid 的绝对值。

程序1:未加入kill函数

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>int main(int argc, char *argv[])
{pid_t pid;pid = fork();//通过fork函数创建一个子进程if(pid < 0){perror("fail to fork");//创建失败exit(1);//退出}else if(pid > 0) //父进程的代码区{int i = 0;while(1){printf("父进程正在运行 %d 次\n", i);i++;sleep(1);}printf("父进程 运行 末尾 \n");}else //子进程的代码区 {printf("子进程正在运行 ... \n");printf("子进程 运行 末尾 \n");}return 0;
}

运行结果:

程序2:加入kill函数

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>int main(int argc, char *argv[])
{pid_t pid;pid = fork();//通过fork函数创建一个子进程if(pid < 0){perror("fail to fork");//创建失败exit(1);//退出}else if(pid > 0) //父进程的代码区{int i = 0;while(1){printf("父进程正在运行 %d 次\n", i);i++;sleep(1);}printf("父进程 运行 末尾 \n");}else //子进程的代码区 {printf("子进程正在运行 ... \n");//子进程在3秒之后,让父进程退出sleep(3);//使用kill给父进程发送信号,然后父进程接收到信号后直接退出就可以了// int kill(pid_t pid, int signum);kill(getppid(), SIGINT);// SIGINT 终止进程(终端按下 Ctrl+C)//kill(getppid(), SIGKILL);// SIGKILL 立即终止进程(kill -9 强制终止,不可捕获或忽略)printf("子进程 运行 末尾 \n");}return 0;
}

运行结果:

3.1 kill命令终端执行

kill 是 Linux/Unix 系统中用于向进程发送信号的命令行工具,核心用途是控制进程的行为(如终止、暂停、恢复或自定义操作)。

3.1.1基本语法

kill [选项] <信号> <进程ID>
kill [选项] -<信号名> <进程ID>

常用选项:

-l:列出所有支持的信号名称和编号。

-s <信号>:指定要发送的信号(默认是 SIGTERM)。

信号表示方式:

信号名(如 SIGTERM、SIGKILL)。

信号编号(如 9 对应 SIGKILL)。

3.1.1.1. 终止进程
  • 默认行为:默认发送 SIGTERM(允许进程优雅退出)。

    kill 1234          # 发送 SIGTERM 到 PID=1234 的进程
    kill -15 1234      # 同上(SIGTERM 的编号是 15)
    
  • 强制终止:发送 SIGKILL(立即终止,不可被捕获或忽略)。

    kill -9 1234       # 强制终止 PID=1234 的进程
    kill -SIGKILL 1234 # 同上(使用信号名)
    kill -s SIGKILL 1234  # 同上(使用信号名)
    
3.1.1.2. 暂停与恢复进程
  • 暂停进程:发送 SIGSTOP(立即暂停进程)。

    kill -SIGSTOP 1234
    
  • 恢复进程:发送 SIGCONT(继续运行被暂停的进程)。

    kill -SIGCONT 1234
    
3.1.1.3. 自定义操作
  • 触发用户定义逻辑:使用 SIGUSR1 或 SIGUSR2
    kill -SIGUSR1 1234 # 通知进程执行自定义操作(如重载配置)
    
3.1.1.4. 批量终止进程
  • 终止同一进程组:使用负 PID(如 -1234 终止进程组 1234)。
    kill -9 -1234      # 强制终止进程组 1234 的所有进程

3.1.2 kill终端运行程序

程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>int main(int argc, char *argv[])
{pid_t pid;pid = fork();//通过fork函数创建一个子进程if(pid < 0){perror("fail to fork");//创建失败exit(1);//退出}else if(pid > 0) //父进程的代码区{int i = 0;while(1){printf("父进程正在运行 %d 次\n", i);i++;sleep(3);}printf("父进程 运行 末尾 \n");}else //子进程的代码区 {printf("子进程正在运行 ... \n");printf("子进程 运行 末尾 \n");}return 0;
}

运行结果:若无kill函数,父进程每隔3秒打印一次。

(1)终端1运行./a.out ,在终端2执行kill命令退出当前进程。

终端2先执行 ps -ajx | grep a.out 命令,ps ajx //前三列分别为 ppid  pid  pgid ,

在根据pid执行kill -9 pid号 命令。

(2)终端1运行./a.out ,在终端2执行kill命令退出当前进程。

终端2先执行 ps -ajx | grep a.out 命令,ps ajx //前三列分别为 ppid  pid  pgid ,

在根据pid执行 kill -s SIGKILL pid号 命令。

(3)终端1运行./a.out ,在终端2执行kill命令退出当前进程。

终端2先执行 ps -ajx | grep a.out 命令,ps ajx //前三列分别为 ppid  pid  pgid ,

在根据pid执行 kill  -SIGKILL pid号 命令。

(4)终端1运行./a.out ,在终端2执行kill命令退出当前进程。

终端2先执行 ps -ajx | grep a.out 命令,ps ajx //前三列分别为 ppid  pid  pgid ,

在根据pid执行 kill  pid号 命令。(kill 默认发送 SIGTERM(允许进程优雅退出))

 (5)终端1运行./a.out ,在终端2执行kill命令退出当前进程。

终端2先执行 ps -ajx | grep a.out 命令,ps ajx //前三列分别为 ppid  pid  pgid ,

在根据pid执行 kill SIGKILL  pid号 命令。

相关文章:

  • flutter 专题 六十三 Flutter入门与实战作者:xiangzhihong8Fluter 应用调试
  • WINDOWS下使用命令行读取本地摄像头FFMPEG+DirectShow,ffplay直接播放摄像头数据
  • 安装ntfs硬盘系统时,报错Error: Unable to find a match: epel-release的解决方法
  • Federated Feature Augmentation and Alignment
  • ECharts散点图-散点图13,附视频讲解与代码下载
  • 机器学习-08-推荐算法-案例
  • Cad c# 射线法判断点在多边形内外
  • 淘宝店铺详情API接口返回数据说明
  • 精益数据分析(10/126):深度剖析数据指标,驱动创业决策
  • EXCEL学习
  • 天元证券|AI驱动需求井喷 光模块上市公司业绩爆发
  • Oracle for Linux安装和配置(11)——Linux配置
  • 深入理解 DML 和 DQL:SQL 数据操作与查询全解析
  • Spring Boot 集成 Redis 实战总结
  • 智能对讲机:通信技术的革新与“危急特”场景的守护者
  • 【KWDB创作者计划】_针对KWDB时序数据库(多副本集群环境)进行压力测试
  • C++如何处理多线程环境下的异常?如何确保资源在异常情况下也能正确释放
  • 【scikit-learn基础】--『监督学习』之 均值聚类
  • Android 15强制edge-to-edge全面屏体验
  • docker部署ruoyi-vue-pro前后端详细笔记
  • 江西省人大教育科学文化卫生委员会主任委员王水平被查
  • 成功卫冕!孙颖莎4比0战胜蒯曼,获澳门世界杯女单冠军
  • 北理工:开除宫某党籍,免去行政职务,解除聘用关系
  • 重点并不在于设计更聪明的机器,而在于开发宇宙技术的多样性
  • 市场监管总局:在全国集中开展食用植物油突出问题排查整治
  • 习近平会见柬埔寨人民党主席、参议院主席洪森