仓库源文站点原文


title: 进程间通信的几种方式总结 toc: true cover: 'https://img.paulzzh.com/touhou/random?3' date: 2021-04-19 09:20:22 categories: 技术杂谈 tags: [技术杂谈, 进程通信, 信号]

description: 进程间通信有多种方式,本文讲述了进程间通信的方法;

进程间通信有多种方式,本文讲述了进程间通信的方法;

<br/>

<!--more-->

进程间通信的几种方式总结

① 管道

在Linux中可以在终端通过|运算符,将前一个进程中的标准输出作为后一个进程中的输入;

例如:

ls | grep txt

<br/>

② 消息队列

操作系统内核提供了消息队列;

而操作系统中的进程都可以操作这个消息队列;

即发送消息并接收其他进程的消息;

<br/>

③ 共享内存

两个进程的虚拟内存映射至真实物理内存的同一段区域;

此时可以通过这个内存区域进行进程间通信;

<br/>

④ 套接字

使用套接字进行进程间通信的方式非常常见,例如:

访问mysql数据库,就是通过3306端口,将访问数据库的进程和数据库进程进行tcp连接;

<font color="#f00">**如果是在本机访问,则不会使用tcp套接字;**</font>

<font color="#f00">**而是使用Linux底层的套接字;**</font>

<br/>

⑤ 信号量

信号量本质上是一个计数器,他控制了多个进程对同一个共享资源的访问;

<br/>

⑥ 信号

一个进程可以向另一个进程发送信号,而另一个进程可以去处理这个信号;

通过kill -l可以查看所有信号:

[root@VM-12-16-centos ~]# 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) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR
31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

一共有64个信号;

SIGINT

使用tail命令查看文件内容:

[root@VM-12-16-centos ~]# tail -f 1.txt 
123
123
aa
bb
cc
dd
ee

此时进程是被阻塞的,我们可以通过Ctrl + C退出进程;

<font color="#f00">**此时`Ctrl + C`就是发送`2)SIGINT`停止进程的!**</font>

<br/>

SIGTERM

使用tail命令查看文件内容:

[root@VM-12-16-centos ~]# tail -f 1.txt 
123
123
aa
bb
cc
dd
ee

打开另一个终端窗口,并使用kill命令杀死该进程;

[root@VM-12-16-centos ~]# ps aux|grep tail
root     12200  0.0  0.0 108096   616 pts/2    S+   09:36   0:00 tail -f 1.txt
root     12968  0.0  0.0 112816   972 pts/3    S+   09:41   0:00 grep --color=auto tail
[root@VM-12-16-centos ~]# kill 12200

此时,终端中的tail进程被杀死:

[root@VM-12-16-centos ~]# tail -f 1.txt 
123
123
aa
bb
cc
dd
ee
Terminated

输出:Terminated

此时使用的是SIGTERM

<br/>

SIGKILL

使用tail命令查看文件内容:

[root@VM-12-16-centos ~]# tail -f 1.txt 
123
123
aa
bb
cc
dd
ee

打开另一个终端窗口,并使用kill命令杀死该进程;

[root@VM-12-16-centos ~]# ps aux|grep tail
root     13270  0.0  0.0 108096   616 pts/2    S+   09:43   0:00 tail -f 1.txt
root     13281  0.0  0.0 112816   972 pts/3    S+   09:43   0:00 grep --color=auto tail
[root@VM-12-16-centos ~]# kill -9 13270

此时,终端中的tail进程被杀死:

[root@VM-12-16-centos ~]# tail -f 1.txt 
123
123
aa
bb
cc
dd
ee
Killed

输出:Killed

此时使用的是SIGKILL

<br/>

Java中捕获信号

在Java中可以通过Signal类注册对不同的Signal信号的响应;

例如:

package io.github.jasonkayzk;

import sun.misc.Signal;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Signal.handle(new Signal("INT"), signal
                -> System.out.println(signal.toString() + "caught"));

        Signal.handle(new Signal("TERM"), signal
                -> System.out.println(signal.toString() + "caught"));

        while (true) {
            Thread.sleep(1000);
            System.out.println(123);
        }
    }
}

<font color="#f00">**由于注册了SIGINT和SIGTERM的handler,此时发送`Crtl+C`或是`kill`信号将无法停止进程;**</font>

<font color="#f00">**但是,不能指定SIGKILL信号量;因为不论应用进程多么顽强,在接收到SIGKILL信号后都要被杀死;**</font>

<br/>