进程间通信(一)管道

进程间通信 (IPC)

(一)操作系统为用户提供进程间通信的目的

进程间因为每一个进程都有一个虚拟地址空间,在保证了进程独立性的同时,(都是操作自己虚拟地址空间,无法访问别人的地址,无法直接通信)却使得进程间无法直接通信,因此需要操作系统给用户提供一些公共的媒介让多个进程都能够通过访问这个媒介进行通信,所以操作系统来提供进程间通信方式,并且因为通信场景不同,提供的方式也有多种。

(二)进程间通信方式的种类

管道: 用于进程间数据的传输
共享内存: 用于进程间的数据共享
消息队列: 用于进程间数据的传输
信号量: 用于实现进程间的控制


管道

管道本质:
	内核中创建的一块缓冲区----通过半双工通信实现数据传输
    即通过让多个进程都能够访问到同一块缓冲区,来实现通信。
管道的分类:

匿名管道 :
这块内核中的缓冲区没有标识,只能用于具有亲缘关系的进程间通信.
创建管道时,操作系统会提供两个操作句柄(文件描述符) ,其中一个用于从管道读取数据,一个向管道写入数据.
子进程通过父进程的方式 ,获取到管道的操作句柄,进而实现访问同一个管道通信,

函数接口:

int pipe(int pipefd[2]);
/*
创建一个管道,向用户通过参数pipefd返回管道的操作句柄
pipefd[0]:  用于从管道读取数据
pipdfd[1]:  用于向管道写入数据
返回值  : 成功返回0 失败返回-1
管道必须创建于创建子进程之前(子进程这样才能复制到管道的操作句柄)

特性:
若管道中没有数据,则read会阻塞;
若管道写满了,则write会阻塞;
管道自带同步与互斥:
同步: 对临界资源访问的合理性.
互斥: 保证同一时间只有一个进程能够访问到临界资源,来保证临界资源访问的安全性.
对管道进行数据操作的大小不超过PIPE_BUF=4096的时候,则保证操作的原子性.
若管道所有的写端被关闭,(表示当前没有进程继续写入数据了),read读完管道中的数据之后,就不会再阻塞,而是返回0.
若管道所读端被关闭,(表示没有进程读取数据了),继续write会触发异常,程序退出

命名管道:
内核中的缓冲区具有标识符(标识符是一个可见于文件系统的管道文件),其他的进程可以通过这个标识符,找到这块缓冲区(通过打开同一个管道文件,进而访问到同一块缓冲区),进而实现通信

命令操作: mkfifo filename
int mkfifo(const char * pathname ,mode_t mode) —创建命名管道文件。
pathname :管道文件名称
mode:文件权限
成功返回0,失败返回-1

会创建一个test.fifo 文件。
打开特性:
若管道文件以只读的方式打开,则会阻塞, 直到这个管道文件被以写的方式打开。
若管道文件以只写的方式打开,则会阻塞,直到这个管道文件以读的方式打开。
若管道以读写的方式打开,则不会阻塞。

前面匿名管道特性对于命名管道也是一样的,只不过多了打开特性
管道特性: 管道生命周期随进程。
半双工通信
自带同步与互斥
提供字节流服务–有序 可靠 的字节流传输 --传输比较灵活

管道的读写特性

  1. .若管道中没有数据,则read会阻塞。直到数据被写入(缓冲区中有数据)
  2. 若管道数据满了,则write会阻塞。 直到数据被读取(缓冲区有空闲空间)
  3. 管道自带同步与互斥
  4. 同步:对临界资源访问的合理性,
  5. 互斥:·通过保证同一时间只有一个进程能够访问临界资源,保证临界资源访问的安全性。
  6. 对管道进行数据操作的大小不超过PIPE_BUF=4096的时候,则保证操作的原子性。
  7. 若管道所有写端被关闭(表示当前没有进程继续写入数据了)
  8. read读完管道中的数据之后,就不会再阻塞了,而是返回0;就不会再读了
  9. 若管道的所有读端被关闭,(表示没有进程读取数据了), 继续write会触发异常,程序退出。
    10.若管管道的read返回0,不仅仅指的是没有读到数据 -
    所有写端被关闭。
    若所有的写端被关闭,则read不会被阻塞,读完
    数据后返回0;
    道所有写端被关闭,则read会返回0
    (关闭所有写端不要忘记自己)
//写端
#include<stdio.h>
 #include<unistd.h>
 #include<stdlib.h>
 #include<sys/stat.h>
 #include<errno.h>
 #include<fcntl.h>
 #include<string.h>
 int main(){
	
	umask(0);
	char * file="./test.fifo";

	int ret=mkfifo(file,0664);
	if(ret<0&&errno!=EEXIST){
		perror("mkfifo error\n");
		return -1;
	}
	printf("create fifo success ");

	int fd=open(file,O_WRONLY);
	if(fd<0){
		perror("open error");
		return -1;
	}
	printf("open fifo success\n");
	while(1){
		char buf[1024]={0};
		scanf("%s",buf);
		
		ret =write(fd,buf,strlen(buf));
		if(ret<0){
			perror("read error");
			return -1;
		}
		
	}
	
	close(fd);	
	return 0;
 }
 
//读端
 #include<stdio.h>
 #include<unistd.h>
 #include<stdlib.h>
 #include<sys/stat.h>
 #include<errno.h>
 #include<fcntl.h>
 
 int main(){
	
	umask(0);
	char * file="./test.fifo";

	int ret=mkfifo(file,0664);
	if(ret<0&&errno!=EEXIST){
		perror("mkfifo error\n");
		return -1;
	}
	printf("create fifo success ");

	int fd=open(file,O_RDONLY);
	if(fd<0){
		perror("open error");
		return -1;
	}
	printf("open fifo success\n");
	while(1){
		char buf[1024]={0};
		ret =read(fd,buf,1023);
		if(ret<0){
			perror("read error");
			return -1;
		}
		printf("buf: [%s]\n",buf);
	}
	
	close(fd);	
	return 0;
 }
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值