目录

原理

栗子


原理

实现进程通信的目的:

数据传输!
共享数据!
通知事件!
资源共享!
进程控制!

早期linux进程间信号(IPC)有3个部分:

  1. UNIX进行通信方式:管道、FIFO、信号;
  2. System V进程通信: System V消息队列、System V信号量、 System V共享内存;
  3. POSIX进程间通信:posix消息队列、posix信号量、posix共享内存;

目前Linux进程通信方式:

  1. 管道(pipe)和命名管道(FIFO);
  2. 信号(signal);
  3. 消息队列;
  4. 共享内存;
  5. 信号量;
  6. 套接字(socket);


管道通信:

  1. 本地计算机的两个进程之间的通信而设计的,管道建立后,获取两个文件的描述符:一个用于写,一个用于读;
  2. 通过pipe系统调用;
  3. 管道是单工的,数据只向一个方向流动,双向流动要建立两个管道;
  4. 数据的读出和写入:一个进程向管道中写的内容被管道另一端读出。写入的内容每次都添加到管道的缓存区的末尾,并且每次都是从缓存区的头部读取数据。

【注意:管道实际上是创建到计算机内核当中的缓存】

管道分类:
匿名管道:

  1. 在关系进程中进行(父进程和子进程、兄弟进程直接);
  2. 由pipe系统调用,管道由父进程建立;
  3. 管道位于内核空间,其实是一块缓存;

命名管道(FIFO):

  1. 两个进程之间没有任何关系,本质上是内核中的一块缓存,另外在文件系统中以一个特殊的设备文件(管道文件)存在。
  2. 通过系统调用mkfifo创建;

【注意可以通过操作这个管道文件就可以了,他会自动同步到缓存中】

注意:
fork子进程后,会复制父进程的数据(代码段,数据段,堆栈等),所以fd(文件描述符)也会被复制
fork函数将运行着的程序分成2个(几乎)完全一样的进程,每个进程都启动一个从代码的同一位置开始执行的线程。这两个进程中的线程继续执行,就像是两个用户同时启动了该应用程序的两个副本。

 

栗子

下面是源码,要注意:

  1. fd[0]:为pipe的读端口;fd[1]:为pipe的写端口;
  2. 要注意,用完,或不用端口就把他关掉;
  3. 父进程要回收下子进程、wait()是等待进程结束;

源码如下:

#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

int main(void){

	int fd[2];

	if(pipe(fd) < 0){
		
		perror("pipe error!");
		exit(1);
	}

	pid_t pid;	
	if((pid = fork()) < 0){
		
		perror("fork error");
		exit(1);
	}
	else if(pid >0 ){	// parent process
	
		close(fd[0]);
		int start = 1, end = 100;

		//往管道中写数据
		if(write(fd[1], &start, sizeof(int)) != sizeof(int)){
			
			perror("write error");
			exit(1);			
		}
		if(write(fd[1], &end, sizeof(int)) != sizeof(int)){
		
			perror("write error");
			exit(1);
		}
		close(fd[1]);
		wait(0);
	}
	else{			//child process

		close(fd[1]);
		int start, end;
		if(read(fd[0], &start, sizeof(int)) < 0){

			perror("read error");
			exit(1);
		}
		if(read(fd[0], &end, sizeof(int)) < 0){
			
			perror("read error");
			exit(1);
		}
		close(fd[0]);
		printf("child process read start: %d , end: %d \n", start, end);
	}

	exit(0);
}

程序运行截图如下:

Logo

更多推荐