进程间通信有多种方式,本文讲述了进程间通信的方法;
进程间通信的几种方式总结
① 管道
在Linux中可以在终端通过|
运算符,将前一个进程中的标准输出作为后一个进程中的输入;
例如:
ls | grep txt
② 消息队列
操作系统内核提供了消息队列;
而操作系统中的进程都可以操作这个消息队列;
即发送消息并接收其他进程的消息;
③ 共享内存
两个进程的虚拟内存映射至真实物理内存的同一段区域;
此时可以通过这个内存区域进行进程间通信;
④ 套接字
使用套接字进行进程间通信的方式非常常见,例如:
访问mysql数据库,就是通过3306端口,将访问数据库的进程和数据库进程进行tcp连接;
如果是在本机访问,则不会使用tcp套接字;
而是使用Linux底层的套接字;
⑤ 信号量
信号量本质上是一个计数器,他控制了多个进程对同一个共享资源的访问;
⑥ 信号
一个进程可以向另一个进程发送信号,而另一个进程可以去处理这个信号;
通过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
退出进程;
此时Ctrl + C
就是发送2)SIGINT
停止进程的!
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
;
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
;
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);
}
}
}
由于注册了SIGINT和SIGTERM的handler,此时发送Crtl+C
或是kill
信号将无法停止进程;
但是,不能指定SIGKILL信号量;因为不论应用进程多么顽强,在接收到SIGKILL信号后都要被杀死;