进程间通信

 

一、基本概念

  • 什么是进程间通信:是指两个或多个进程之间交互数据的过程,因为进程之间是相互独立的,为了进程间协同工作就必须实现进程间交互数据

进程间通信的分类:

  • 简单的进程间通信:信号、普通文件、环境变量表、命令行参数
  • 传统的进程间通信:管道文件
  • XSI的进程间通信: 共享内存、消息队列、信号量
  • 网络进程间通信:Socket套接字

二、传统的进程间通信-管道文件

  • 管道是UNIX系统中最古老的进程间通信技术,古老意味着所有系统都支持,早期的管道是半双工通信,现有的系统管道是全双工通信
  • 管道就是一种特殊的文件,数据在文件中是流动的,读取之后就自动消失,如果文件中没有数据则会阻塞

有名管道:基于有文件名的管道文件的通信

        编程模型

                进程A                 进程B

                创建管道

                打开管道           打开管道

                写数据               读数据

                关闭管道           关闭管道

                删除管道

创建有名管道文件:

        1、命令 mkfifo

        2、函数

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

                        功能:创建有名管道

                        pathname:管道文件路径

                        mode:管道文件权限 0664

管道A

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

int main(int argc,const char* argv[])
{
	//	创建管道文件
	if(mkfifo("fifo",0664))
	{
		perror("mkfifo");
		return -1;
	}

	//	打开
	int fd = open("fifo",O_WRONLY);
	if(0 > fd)
	{
		perror("open");
		unlink("fifo");
		return -1;
	}

	//	写数据
	char buf[256] = {};
	for(;;)
	{
		printf(">>>");
		scanf("%s",buf);
		write(fd,buf,strlen(buf)+1);
		if(0 == strcmp(buf,"quit"))
		{
			printf("通信结束!\n");
			break;
		}
	}
	//	关闭删除
	close(fd);
	usleep(1000);
	unlink("fifo");
}

管道B

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

int main(int argc,const char* argv[])
{
	//	打开
	int fd = open("fifo",O_RDONLY);
	if(0 > fd)
	{
		perror("open");
		return -1;
	}

	//	读数据
	char buf[256] = {};
	for(;;)
	{
		read(fd,buf,sizeof(buf));
		printf("read:%s\n",buf);
		if(0 == strcmp(buf,"quit"))
		{
			printf("通信结束!\n");
			break;
		}
	}
	//	关闭
	close(fd);
}

匿名管道:只适合通过fork创建父子进程之间使用

        int pipe(int pipefd[2]);

                功能:创建一个匿名管道文件

                通过pipefd返回该匿名管道文件的读权限fd和写权限的fd

                pipefd[0] 用于读匿名管道

                pipefd[1] 用于写匿名管道

        编程模型:

                父进程                 子进程

                获取一对fd

                创建子进程         拷贝\共享一对fd

                关闭读                 关闭写

                写数据                 读数据

                关闭写                 关闭读

三、XSI进程间通信

X/open公司制定的用于进程间通信的系统(S)接口(I)

XSI进程间通信都需要借助系统内核完成,需要创建内核对象,内核对象会以整数形式返回给用户态,类似于文件描述符,也叫做IPC标识符

文件的创建打开需要借助文件名,IPC内核对象需要借助IPC键值(整数),必须要确保IPC键值是独一无二的

        key_t ftok(const char *pathname, int proj_id);

                功能:计算出一个独一无二的IPC键值

                pathname:项目路径

                proj_id:项目标号

                返回值:计算出来的IPC键值

        注意:项目路径必须真实存在,否则计算出来的key永远相同

        共享内存:

        基础特点:

                两个或多个进程之间共享一块由内核负责统一管理内存,该内存可以与多个进程的虚拟内存进行映射

        int shmget(key_t key,size_t size,int shmflg);

                功能:创建\获取一块共享内存

                key:IPC键值

                size:共享内存的大小,获取共享内存时此参数无意义,一般给0

        shmflg:

                IPC_CREAT 创建共享内存,如已存在直接获取

                IPC_EXCL 共享内存已存在,返回失败

                获取时直接给0

        注意:如果是创建共享内存还需要额外提供共享内存的权限 例如:IPC_CREAT|0664

        返回值:IPC标识符,失败-1

void *shmat(int shmid,const void *shmaddr, int shmflg);

        功能:让虚拟内存与共享内存进行映射

        shmid:IPC标识符 shmget的返回值

        shmaddr:想要映射的虚拟内存首地址,为NULL时系统会自动分配地址

shmflg:

        SHM_RDONLY 以只读方式映射共享内存

        SHM_RND:只有shmaddr参数不为NULL时才有有效,表示从shmaddr开始向下以整数页方式映射

返回值:与共享内存映射成功后的虚拟内存首地址,失败返回(void *) -1

int shmdt(const void *shmaddr);

        功能:取消映射

        shmaddr:映射成功后的虚拟内存首地址

int shmctl(int shmid,int cmd,struct shmid_ds *buf);

        功能:删除/控制共享内存

        shmid:IPC标识符

cmd:

        IPC_STAT 获取共享内存属性 buf输出型参数

        IPC_SET 设置共享内存属性 buf输入型参数

        IPC_RMID 删除共享内存 NULL

buf

编程模型:

进程A                         进程B

创建共享内存             获取共享内存

映射共享内存             映射共享内存

写数据并通知其他进程 收到通知并读数据

收到通知并读数据      写数据并通知其他进程

取消映射                    取消映射

删除共享内存

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值