linux进程间通信(代码片段)

2021dragon 2021dragon     2023-02-01     222

关键词:

进程间通信介绍

进程间通信的概念

进程间通信简称IPC(Interprocess communication),进程间通信就是在不同进程之间传播或交换信息。

进程间通信的目的

  • 数据传输: 一个进程需要将它的数据发送给另一个进程。
  • 资源共享: 多个进程之间共享同样的资源。
  • 通知事件: 一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件,比如进程终止时需要通知其父进程。
  • 进程控制: 有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。

进程间通信的本质

进程间通信的本质就是,让不同的进程看到同一份资源。

由于各个运行进程之间具有独立性,这个独立性主要体现在数据层面,而代码逻辑层面可以私有也可以公有(例如父子进程),因此各个进程之间要实现通信是非常困难的。

各个进程之间若想实现通信,一定要借助第三方资源,这些进程就可以通过向这个第三方资源写入或是读取数据,进而实现进程之间的通信,这个第三方资源实际上就是操作系统提供的一段内存区域。

因此,进程间通信的本质就是,让不同的进程看到同一份资源(内存,文件内核缓冲等)。 由于这份资源可以由操作系统中的不同模块提供,因此出现了不同的进程间通信方式。

进程间通信的分类

管道

  • 匿名管道
  • 命名管道

System V IPC

  • System V 消息队列
  • System V 共享内存
  • System V 信号量

POSIX IPC

  • 消息队列
  • 共享内存
  • 信号量
  • 互斥量
  • 条件变量
  • 读写锁

管道

什么是管道

管道是Unix中最古老的进程间通信的形式,我们把从一个进程连接到另一个进程的数据流称为一个“管道”。

例如,统计我们当前使用云服务器上的登录用户个数。

其中,who命令和wc命令都是两个程序,当它们运行起来后就变成了两个进程,who进程通过标准输出将数据打到“管道”当中,wc进程再通过标准输入从“管道”当中读取数据,至此便完成了数据的传输,进而完成数据的进一步加工处理。

注明: who命令用于查看当前云服务器的登录用户(一行显示一个用户),wc -l用于统计当前的行数。

匿名管道

匿名管道的原理

匿名管道用于进程间通信,且仅限于本地父子进程之间的通信。

进程间通信的本质就是,让不同的进程看到同一份资源,使用匿名管道实现父子进程间通信的原理就是,让两个父子进程先看到同一份被打开的文件资源,然后父子进程就可以对该文件进行写入或是读取操作,进而实现父子进程间通信。

注意:

  • 这里父子进程看到的同一份文件资源是由操作系统来维护的,所以当父子进程对该文件进行写入操作时,该文件缓冲区当中的数据并不会进行写时拷贝。
  • 管道虽然用的是文件的方案,但操作系统一定不会把进程进行通信的数据刷新到磁盘当中,因为这样做有IO参与会降低效率,而且也没有必要。也就是说,这种文件是一批不会把数据写到磁盘当中的文件,换句话说,磁盘文件和内存文件不一定是一一对应的,有些文件只会在内存当中存在,而不会在磁盘当中存在。

pipe函数

pipe函数用于创建匿名管道,pip函数的函数原型如下:

int pipe(int pipefd[2]);

pipe函数的参数是一个输出型参数,数组pipefd用于返回两个指向管道读端和写端的文件描述符:

数组元素含义
pipefd[0]管道读端的文件描述符
pipefd[1]管道写端的文件描述符

pipe函数调用成功时返回0,调用失败时返回-1。

匿名管道使用步骤

在创建匿名管道实现父子进程间通信的过程中,需要pipe函数和fork函数搭配使用,具体步骤如下:

1、父进程调用pipe函数创建管道。

2、父进程创建子进程。

3、父进程关闭写端,子进程关闭读端。

注意:

  1. 管道只能够进行单向通信,因此当父进程创建完子进程后,需要确认父子进程谁读谁写,然后关闭相应的读写端。
  2. 从管道写端写入的数据会被内核缓冲,直到从管道的读端被读取。

我们可以站在文件描述符的角度再来看看这三个步骤:

1、父进程调用pipe函数创建管道。

2、父进程创建子进程。

3、父进程关闭写端,子进程关闭读端。

例如,在以下代码当中,子进程向匿名管道当中写入10行数据,父进程从匿名管道当中将数据读出。

//child->write, father->read                                                                                                                                                                                                                                                                                                                                                                                                                                                        
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()

	int fd[2] =  0 ;
	if (pipe(fd) < 0) //使用pipe创建匿名管道
		perror("pipe");
		return 1;
	
	pid_t id = fork(); //使用fork创建子进程
	if (id == 0)
		//child
		close(fd[0]); //子进程关闭读端
		//子进程向管道写入数据
		const char* msg = "hello father, I am child...";
		int count = 10;
		while (count--)
			write(fd[1], msg, strlen(msg));
			sleep(1);
		
		close(fd[1]); //子进程写入完毕,关闭文件
		exit(0);
	
	//father
	close(fd[1]); //父进程关闭写端
	//父进程从管道读取数据
	char buff[64];
	while (1)
		ssize_t s = read(fd[0], buff, sizeof(buff));
		if (s > 0)
			buff[s] = '\\0';
			printf("child send to father:%s\\n", buff);
		
		else if (s == 0)
			printf("read file end\\n");
			break;
		
		else
			printf("read error\\n");
			break;
		
	
	close(fd[0]); //父进程读取完毕,关闭文件
	waitpid(id, NULL, 0);
	return 0;

运行结果如下:

管道读写规则

pipe2函数与pipe函数类似,也是用于创建匿名管道,其函数原型如下:

int pipe2(int pipefd[2], int flags);

pipe2函数的第二个参数用于设置选项。

1、当没有数据可读时:

  • O_NONBLOCK disable:read调用阻塞,即进程暂停执行,一直等到有数据来为止。
  • O_NONBLOCK enable:read调用返回-1,errno值为EAGAIN。

2、当管道满的时候:

  • O_NONBLOCK disable:write调用阻塞,直到有进程读走数据。
  • O_NONBLOCK enable:write调用返回-1,errno值为EAGAIN。

3、如果所有管道写端对应的文件描述符被关闭,则read返回0。
4、如果所有管道读端对应的文件描述符被关闭,则write操作会产生信号SIGPIPE,进而可能导致write进程退出。
5、当要写入的数据量不大于PIPE_BUF时,Linux将保证写入的原子性。
6、当要写入的数据量大于PIPE_BUF时,Linux将不再保证写入的原子性。

管道的特点

1、管道内部自带同步与互斥机制。

我们将一次只允许一个进程使用的资源,称为临界资源。管道在同一时刻只允许一个进程对其进行写入或是读取操作,因此管道也就是一种临界资源。

临界资源是需要被保护的,若是我们不对管道这种临界资源进行任何保护机制,那么就可能出现同一时刻有多个进程对同一管道进行操作的情况,进而导致同时读写、交叉读写以及读取到的数据不一致等问题。

为了避免这些问题,内核会对管道操作进行同步与互斥:

  • 同步: 两个或两个以上的进程在运行过程中协同步调,按预定的先后次序运行。比如,A任务的运行依赖于B任务产生的数据。
  • 互斥: 一个公共资源同一时刻只能被一个进程使用,多个进程不能同时使用公共资源。

实际上,同步是一种更为复杂的互斥,而互斥是一种特殊的同步。对于管道的场景来说,互斥就是两个进程不可以同时对管道进行操作,它们会相互排斥,必须等一个进程操作完毕,另一个才能操作,而同步也是指这两个不能同时对管道进行操作,但这两个进程必须要按照某种次序来对管道进行操作。

也就是说,互斥具有唯一性和排它性,但互斥并不限制任务的运行顺序,而同步的任务之间则有明确的顺序关系。

2、管道的生命周期随进程。

管道本质上是通过文件进行通信的,也就是说管道依赖于文件系统,那么当所有打开该文件的进程都退出后,该文件也就会被释放掉,所以说管道的生命周期随进程。

3、管道提供的是流式服务。

对于进程A写入管道当中的数据,进程B每次从管道读取的数据的多少是任意的,这种被称为流式服务,与之相对应的是数据报服务:

  • 流式服务: 数据没有明确的分割,不分一定的报文段。
  • 数据报服务: 数据有明确的分割,拿数据按报文段拿。

4、管道是半双工通信的。

在数据通信中,数据在线路上的传送方式可以分为以下三种:

  1. 单工通信(Simplex Communication):单工模式的数据传输是单向的。通信双方中,一方固定为发送端,另一方固定为接收端。
  2. 半双工通信(Half Duplex):半双工数据传输指数据可以在一个信号载体的两个方向上传输,但是不能同时传输。
  3. 全双工通信(Full Duplex):全双工通信允许数据在两个方向上同时传输,它的能力相当于两个单工通信方式的结合。全双工可以同时(瞬时)进行信号的双向传输。

管道是半双工的,数据只能向一个方向流动,需要双方通信时,需要建立起两个管道。

管道的四种特殊情况

在使用管道时,可能出现以下四种特殊情况:

  1. 写端进程不写,读端进程一直读,那么此时会因为管道里面没有数据可读,对应的读端进程会被挂起,直到管道里面有数据后,读端进程才会被唤醒。
  2. 读端进程不读,写端进程一直写,那么当管道被写满后,对应的写端进程会被挂起,直到管道当中的数据被读端进程读取后,写端进程才会被唤醒。
  3. 写端进程将数据写完后将写端关闭,那么读端进程将管道当中的数据读完后,就会继续执行该进程之后的代码逻辑,而不会被挂起。
  4. 读端进程将读端关闭,而写端进程还在一直向管道写入数据,那么操作系统会将写端进程杀掉。

其中前面两种情况就能够很好的说明,管道是自带同步与互斥机制的,读端进程和写端进程是有一个步调协调的过程的,不会说当管道没有数据了读端还在读取,而当管道已经满了写端还在写入。读端进程读取数据的条件是管道里面有数据,写端进程写入数据的条件是管道当中还有空间,若是条件不满足,则相应的进程就会被挂起,直到条件满足后才会被再次唤醒。

第三种情况也很好理解,读端进程已经将管道当中的所有数据都读取出来了,而且此后也不会有写端再进行写入了,那么此时读端进程也就可以执行该进程的其他逻辑了,而不会被挂起。

第四种情况也不难理解,既然管道当中的数据已经没有进程会读取了,那么写端进程的写入将没有意义,因此操作系统直接将写端进程杀掉。而此时子进程代码都还没跑完就被终止了,属于异常退出,那么子进程必然收到了某种信号。

我们可以通过以下代码看看情况四中,子进程退出时究竟是收到了什么信号。

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()

	int fd[2] =  0 ;
	if (pipe(fd) < 0) //使用pipe创建匿名管道
		perror("pipe");
		return 1;
	
	pid_t id = fork(); //使用fork创建子进程
	if (id == 0)
		//child
		close(fd[0]); //子进程关闭读端
		//子进程向管道写入数据
		const char* msg = "hello father, I am child...";
		int count = 10;
		while (count--)
			write(fd[1], msg, strlen(msg));
			sleep(1);
		
		close(fd[1]); //子进程写入完毕,关闭文件
		exit(0);
	
	//father
	close(fd[1]); //父进程关闭写端
	close(fd[0]); //父进程直接关闭读端(导致子进程被操作系统杀掉)
	int status = 0;
	waitpid(id, &status, 0);
	printf("child get signal:%d\\n", status & 0x7F); //打印子进程收到的信号
	return 0;

运行结果显示,子进程退出时收到的是13号信号。

通过kill -l命令可以查看13对应的具体信号。

[cl@VM-0-15-centos nonamepipe]$ kill -l


由此可知,当发生情况四时,操作系统向子进程发送的是SIGPIPE信号将子进程终止的。

管道的大小

管道的容量是有限的,如果管道已满,那么写端将阻塞或失败,那么管道的最大容量是多少呢?

方法一:使用man手册

根据man手册,在2.6.11之前的Linux版本中,管道的最大容量与系统页面大小相同,从Linux 2.6.11往后,管道的最大容量是65536字节。

然后我们可以使用uname -r命令,查看自己使用的Linux版本。

根据man手册,我使用的是Linux 2.6.11之后的版本,因此管道的最大容量是65536字节。

方法二:使用ulimit命令

其次,我们还可以使用ulimit -a命令,查看当前资源限制的设定。

根据显示,管道的最大容量是 512 × 8 = 4096 512\\times8=4096 512×8=4096 字节。

方法三:自行测试

这里发现,根据man手册得到的管道容量与使用ulimit命令得到的管道容量不同,那么此时我们可以自行进行测试。

前面说到,若是读端进程一直不读取管道当中的数据,写端进程一直向管道写入数据,当管道被写满后,写端进程就会被挂起。据此,我们可以写出以下代码来测试管道的最大容量。

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()

	int fd[2] =  0 ;
	if (pipe(fd) < 0) //使用pipe创建匿名管道
		perror("pipe");
		return 1;
	
	pid_t id = fork(); //使用fork创建子进程
	if (id == 0)
		//child 
		close(fd[0]); //子进程关闭读端
		char c = 'a';
		int count = 0;
		//子进程一直进行写入,一次写入一个字节
		while (1)
			write(fd[1], &c, 1);
			count++;
			printf("%d\\n", count); //打印当前写入的字节数
		
		close(fd[1]);
		exit(0);
	
	//father
	close(fd[1]); //父进程关闭写端

	//父进程不进行读取

	waitpid(id, NULL, 0);
	close(fd[0]);
	return 0;

可以看到,在读端进程不进行读取的情况下,写端进程最多写65536字节的数据就被操作系统挂起了,也就是说,我当前Linux版本中管道的最大容量是65536字节。

命名管道

命名管道的原理

匿名管道只能用于具有共同祖先的进程(具有亲缘关系的进程)之间的通信,通常,一个管道由一个进程创建,然后该进程调用fork,此后父子进程之间就可应用该管道。
如果要实现两个毫不相关进程之间的通信,可以使用命名管道来做到。命名管道就是一种特殊类型的文件,两个进程通过命名管道的文件名打开同一个管道文件,此时这两个进程也就看到了同一份资源,进而就可以进行通信了。

注意:

  1. 普通文件是很难做到通信的,即便做到通信也无法解决一些安全问题。
  2. 命名管道和匿名管道一样,都是内存文件,只不过命名管道在磁盘有一个简单的映像,但这个映像的大小永远为0,因为命名管道和匿名管道都不会将通信数据刷新到磁盘当中。

使用命令创建命名管道

我们可以使用mkfifo命令创建一个命名管道。

[cl@VM-0-15-centos fifo]$ mkfifo fifo


可以看到,创建出来的文件的类型是p,代表该文件是命名管道文件。

使用这个命名管道文件,就能实现两个进程之间的通信了。我们在一个进程(进程A)中用shell脚本每秒向命名管道写入一个字符串,在另一个进程(进程B)当中用cat命令从命名管道当中进行读取。
现象就是当进程A启动后,进程B会每秒从命名管道中读取一个字符串打印到显示器上。这就证明了这两个毫不相关的进程可以通过命名管道进行数据传输,即通信。

之前我们说过,当管道的读端进程退出后,写端进程再向管道写入数据就没有意义了,此时写端进程会被操作系统杀掉,在这里就可以很好的得到验证:当我们终止掉读端进程后,因为写端执行的循环脚本是由命令行解释器bash执行的,所以此时bash就会被操作系统杀掉,我们的云服务器也就退出了。

创建一个命名管道

在程序中创建命名管道使用mkfifo函数,mkfifo函数的函数原型如下:

int mkfifo(const char *pathname, mode_t mode);

mkfifo函数的第一个参数是pathname,表示要创建的命名管道文件。

  • 若pathname以路径的方式给出,则将命名管道文件创建在pathname路径下。
  • 若pathname以文件名的方式给出,则将命名管道文件默认创建在当前路径下。(注意当前路径的含义)

mkfifo函数的第二个参数是mode,表示创建命名管道文件的默认权限。

例如,将mode设置为0666,则命名管道文件创建出来的权限如下:

但实际上创建出来文件的权限值还会受到umask(文件默认掩码)的影响,实际创建出来文件的权限为:mode&(~umask)。umask的默认值一般为0002,当我们设置mode值为0666时实际创建出来文件的权限为0664。

若想创建出来命名管道文件的权限值不受umask的影响,则需要在创建文件前使用umask函数将文件默认掩码设置为0。

umask(0); //将文件默认掩码设置为0

mkfifo函数的返回值。

  • 命名管道创建成功,返回0。
  • 命名管道创建失败,返回-1。

创建命名管道示例:

使用以下代码即可在当前路径下,创建出一个名为myfifo的命名管道。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

#define FILE_NAME "myfifo"

int main()

	umask(0); //将文件默认掩码设置为0
	if (mkfifo(FILE_NAME, 0666) < 0) //使用mkfifo创建命名管道文件
		perror("mkfifo");
		return 1;
	

	//create success...

	return 0;

运行代码后,命名管道myfifo就在当前路径下被创建了。

命名管道的打开规则

1、如果当前打开操作是为读而打开FIFO时。

  • O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFO。
  • O_NONBLOCK enable:立刻返回成功。

2、如果当前打开操作是为写而打开FIFO时。

  • O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFO。
  • O_NONBLOCK enable:立刻返回失败,错误码为ENXIO。

用命名管道实现serve&client通信

实现服务端(server)和客户端(client)之间的通信之前,我们需要先让服务端运行起来,我们需要让服务端运行后创建一个命名管道文件,然后再以读的方式打开该命名管道文件,之后服务端就可以从该命名管道当中读取客户端发来的通信信息了。

服务端的代码如下:

//server.c
#include "comm.h"

int main()

	umask(0); //将文件默认掩码设置为0
	if (mkfifo(FILE_NAME, 0666) < 0) //使用mkfifo创建命名管道文件
		perror("mkfifo");
		return 1;
	
	int fd = open(FILE_NAME, O_RDONLY); //以读的方式打开命名管道文件
	if (fd < 0)
		perror("open");
		return 2;
	
	char msg[128];
	while (1)
		msg[0] = '\\0'; //每次读之前将msg清空
		//从命名管道当中读取信息
		ssize_t s = read(fd, msg, sizeof(msg)-1);
		if (s > 0)
			msg[s] = '\\0'; //手动设置'\\0',便于输出
			printf("client# %s\\n", msg); //输出客户端发来的信息
		
		else if (s == 0)
			printf("client quit!\\n");
			break;
		
		else
			printf("read error!\\n");
			break;
		
	
	close(fd); 查看详情  

linux之进程间通信(代码片段)

进程间通信文章目录进程间通信进程间通信的目的进程间通信分类管道什么是管道匿名管道pipe函数用fork来共享管道原理站在文件描述符角度理解管道管道读写规则管道的特性命名管道systemV共享内存共享内存的基本原理申请共享... 查看详情

linux进程间通信(代码片段)

等你穿过暴风雨,你就不再是原来的你。linux进程间通信管道匿名管道匿名管道的创建命名管道命名管道的创建管道的读写规则管道的特点SYSTEMV共享内存共享内存原理共享内存示意图共享内存函数ftokshmgetshmatshmdtshmctl进程间... 查看详情

linux进程间通信(代码片段)

等你穿过暴风雨,你就不再是原来的你。linux进程间通信管道匿名管道匿名管道的创建命名管道命名管道的创建管道的读写规则管道的特点SYSTEMV共享内存共享内存原理共享内存示意图共享内存函数ftokshmgetshmatshmdtshmctl进程间... 查看详情

[linux]进程间通信(代码片段)

文章目录1进程间通信1.1通信方式1.1.1管道1.1.1.1匿名管道1.1.1.2命名管道1.1.2SystemV1.2信号量结尾1进程间通信进程间通信的本质:让进程看到同一块空间,俩进程对这一块内存进行读写。其通信的作用就是传输数据,资源... 查看详情

linux入门进程间的通信(代码片段)

进程间通信进程间通信介绍进程间通信目的进程间通信发展进程间通信分类管道什么是管道匿名管道用fork来共享管道的原理站在内核角度-深度理解管道站在内核角度-管道的本质管道读写规则管道特点命名管道创建一个命名管道... 查看详情

linux进程间通信(代码片段)

【linux】进程间通信紧接上篇【linux】进程控制,现来讨论进程间通信。01.概念进程是一个独立的资源分配单元,不同进程(这里所说的进程通常指的是用户进程)之间的资源是独立的,没有关联,不能在... 查看详情

linux操作系统进程间通信(代码片段)

文章目录1.进程间通信介绍1.1进程间通信的目的1.2进程间通信的发展1.3进程间通信分类2.管道2.1匿名管道2.2命名管道3.SystemV3.1共享内存①shmget②shmctl③shmat④shmdt⑤申请共享内存大小的问题⑥structshmid_ds3.2信号量1.进程间通信介绍进... 查看详情

linux操作系统进程间通信(代码片段)

文章目录1.进程间通信介绍1.1进程间通信的目的1.2进程间通信的发展1.3进程间通信分类2.管道2.1匿名管道2.2命名管道3.SystemV3.1共享内存①shmget②shmctl③shmat④shmdt⑤申请共享内存大小的问题⑥structshmid_ds3.2信号量1.进程间通信介绍进... 查看详情

linux进程间通信消息队列实现两个进程间通信(代码片段)

例子:通过消息队列实现两个进程间通信,一个进程从终端输入数据,通过消息队列发送,另一个进程通过消息队列接收数据  文件1创建进程1终端输入通过消息队列发送数据#include<stdio.h>#include<stdlib.h>#include<errno.h&... 查看详情

linux中进程间通信(代码片段)

一、整体大纲二、进程间通信概念及方法    Linux环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间。任何一个进程的全局变量在另一个进程中都看不到,所以进程和进程之间不能相互访问,要... 查看详情

《linux从0到99》十进程间通信(代码片段)

进程间通信一、什么是进程间通信1.进程间通信的目的2.进程间通信的分类二、管道1.管道01管道的符号02管道的本质2.匿名管道与命名管道01匿名管道02命名管道三、消息队列四、共享内存1.共享内存的原理2.共享内存接口01shmget02shm... 查看详情

linux进程通信之匿名管道(代码片段)

进程间的通信方式  进程间的通信方式包括,管道、共享内存、信号、信号量、消息队列、套接字。进程间通信的目的  进程间通信的主要目的是:数据传输、数据共享、事件通知、资源共享、进程控制等。进程间通信之管... 查看详情

linux进程间通信实例(pipesharedmemorysocket)(代码片段)

在Linux下的多个进程间的通信机制叫做IPC(Inter-ProcessCommunication),它是多个进程之间相互沟通的一种方法。Linux中提供有多种进程间通信的方法:管道(Pipes)FIFO(或称namedpipes)消息队列Unix-domainSocket共享内存(Sharedmemory)本文... 查看详情

linux进程间通信总结(代码片段)

进程间通信的概念每个进程各自有不同的用户地址空间,任何一个进程的变量在另一个进程中都是看不到的,所以进程之间要交换数据必须通过内核,在内核中开辟出一块缓冲区。一个进程把自己的数据从用户空间拷... 查看详情

[os-linux]详解linux的进程间通信1------管道(代码片段)

本文详解了Linux中进程间通信,包括了进程间通信的介绍,匿名管道和命名管道。目录一、进程间通信的介绍1.进程间通信目的2.进程间通信分类二、管道1.管道是什么2.匿名管道  (1)pipe (2)实现 (3)用... 查看详情

[os-linux]详解linux的进程间通信1------管道(代码片段)

本文详解了Linux中进程间通信,包括了进程间通信的介绍,匿名管道和命名管道。目录一、进程间通信的介绍1.进程间通信目的2.进程间通信分类二、管道1.管道是什么2.匿名管道  (1)pipe (2)实现 (3)用... 查看详情

linux进程间通信(ipc)总结(代码片段)

概述一个大型的应用系统,往往需要众多进程协作,进程(Linux进程概念见附1)间通信的重要性显而易见。本系列文章阐述了 Linux环境下的几种主要进程间通信手段。进程隔离进程隔离是为保护操作系统中进程互不干扰而设... 查看详情