进程间通信的几种方式总结
进程间通信有多种方式,本文讲述了进程间通信的方法;
进程间通信的几种方式总结
① 管道
在Linux中可以在终端通过|运算符,将前一个进程中的标准输出作为后一个进程中的输入;
例如:
② 消息队列
操作系统内核提供了消息队列;
而操作系统中的进程都可以操作这个消息队列;
即发送消息并接收其他进程的消息;
③ 共享内存
两个进程的虚拟内存映射至真实物理内存的同一段区域;
此时可以通过这个内存区域进行进程间通信;
④ 套接字
使用套接字进行进程间通信的方式非常常见,例如:
访问mysql数据库,就是通过3306端口,将访问数据库的进程和数据库进程进行tcp连接;
如果是在本机访问,则不会使用tcp套接字;
而是使用Linux底层的套接字;
⑤ 信号量
信号量本质上是一个计数器,他控制了多个进程对同一个共享资源的访问;
⑥ 信号
一个进程可以向另一个进程发送信号,而另一个进程可以去处理这个信号;
通过kill -l可以查看所有信号:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| [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命令查看文件内容:
1 2 3 4 5 6 7 8
| [root@VM-12-16-centos ~]# tail -f 1.txt 123 123 aa bb cc dd ee
|
此时进程是被阻塞的,我们可以通过Ctrl + C退出进程;
此时Ctrl + C就是发送2)SIGINT停止进程的!
SIGTERM
使用tail命令查看文件内容:
1 2 3 4 5 6 7 8
| [root@VM-12-16-centos ~]# tail -f 1.txt 123 123 aa bb cc dd ee
|
打开另一个终端窗口,并使用kill命令杀死该进程;
1 2 3 4
| [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进程被杀死:
1 2 3 4 5 6 7 8 9
| [root@VM-12-16-centos ~]# tail -f 1.txt 123 123 aa bb cc dd ee Terminated
|
输出:Terminated;
此时使用的是SIGTERM;
SIGKILL
使用tail命令查看文件内容:
1 2 3 4 5 6 7 8
| [root@VM-12-16-centos ~]# tail -f 1.txt 123 123 aa bb cc dd ee
|
打开另一个终端窗口,并使用kill命令杀死该进程;
1 2 3 4
| [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进程被杀死:
1 2 3 4 5 6 7 8 9
| [root@VM-12-16-centos ~]# tail -f 1.txt 123 123 aa bb cc dd ee Killed
|
输出:Killed;
此时使用的是SIGKILL;
Java中捕获信号
在Java中可以通过Signal类注册对不同的Signal信号的响应;
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 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信号后都要被杀死;