今天我们接着谈Linux系统编程中的进程间的通信,上一节我们讨论了进程的基本操作。这一节我们来讨论一下进程间的通信。
        常见的进程间的通信方式有:无名管道、命名管道、信号、共享内存、消息队列、信号量、套接字。


接下来我们先来谈:
                一、无名管道:
                      1、管道是UNIX系统的IPC的最古老方式,并且多数unix系统都提供此种通信方式。、
                      2、管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
                      3、虽然管道是半双工的,但是我们可以通过创建两个无名管道实现父子进程间的相互通信。我们来看下图常用的编程模型:

4、函数原型:

       #include <unistd.h>int pipe(int pipefd[2]);

5、上面就是无名管道的一些基本语法,当使用无名管道通信的时候,在父进程创建子进程之前,我们创建的数据都是共享的,所以,通过在fork之前创建管道就可以实现父子进程之间的通信,这里给出一个测试用例,帮助理解如何使用管道:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<errno.h>#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>#define BUFSIZE 1024int main()
{pid_t pid = -1;char str[BUFSIZE] = {0};//先实现单双工,父写子读int fd[1];int res = -1;res = pipe(fd);if(-1 == res){perror("pipe");exit(1);}pid = fork();if(pid > 0){//父进程,父写子读,就需要在父进程关闭读端,0读1写printf("I am Parent\n");memset(str,0,BUFSIZE);int status = 0;//关闭读端close(fd[0]);strcpy(str,"Hello World Hello Linux\n");//向管道写数据res =  write(fd[1],str,strlen(str));if(-1 == res){perror("write");exit(1);}res = wait(status);if(-1 == res){perror("wait ");exit(1);}}else if(0 == pid){//子进程,父写子读,在子进程里关闭写端printf("I am child\n");close(fd[1]);memset(str,0,BUFSIZE);res = read(fd[0],str,BUFSIZE);if(-1 == res ){perror("resd ");exit(1);}res = write(STDOUT_FILENO,str,strlen(str));if(-1 == res){perror("write");exit(1);}}return 0;
}

上边给出了半双工的无名管道的通信方式,所谓全双工的测试代码,就是在创建进程之前创建两个管道,在父子进程中分别关掉一个读写端,这样就可以实现父子进程间通信。虽然这样实现了父子进程间的通信,我们也能看到一个问题,有名管道只能用到有亲缘关系的父子进程间通信。这样是很不方便的,下来我们来看有名管道:


二、 FIFO(有名管道)

a、基础概念:

FIFO有时被命名为命名管道。管道只能由相关进程使用,这些相关进程的共同祖先进程创建了管道。通过FIFO不相关的进程也能交换数据。
                    FIFO是一种文件类型。stat结构成员st_mode的编码指明文件是否是FIFO类型,可以用S_ISFIFO宏对其进行测试。
                    b、函数原型:
                        创建FIFO类似于创建文件。
                        #include <sys/types.h>
                        #include <sys/stat.h>
                        int mkfifo(const char *pathname, mode_t mode);
                   一旦已经用了mkfifo创建了一个FIFO,就可用open打开它。其实,一般的文件I/O函数(close、read、write、unlink等)都可以用。 
                    c、FIFO的两种用途:
                        1、FIFO由shell命令使用以便将数据从一条管线传送到另一条,为此无需创建中间临时文件。
                        2、FIFO用于客户进程-服务器进程应用程序中,一再客户进程和服务器进程之间传递数据
                    d、 实例:
                        1、FIFO复制输出流:
                            FIFO可以复制串行管道命令之间的输出流,于是也就不需要写数据到中间磁盘文件中。管道只能用于进程间的线性连接,然而FIFO可以用来非线性连接。
                        2、客户-服务器进程
                    FIFO的另一个应用就是在客户进程和服务器进程之间传输数据。如果有一个服务器进程,它与多个客户进程都可以将其请求写到一个该服务器进程创建的众所周知的FIFO中,这中类型的客户进程-服务器进程通信中使用FIFO的问题是:服务器如何将回答送回各个客户进程。
                不能使用单个FIFO,因为该服务器进程发出对各个客户进程的请求响应,而请求者却不能知道什么时候去读才能恰如其分的读到对它的相应。一种解决方法是每个客户进程都在其请求中包含它的进程ID。然后服务器进程为每个进程创建一个FIFO,所使用的路径名是以客户进程的进程ID为基础的。

3、下来我们来看具体代码:

我们用mkfifo实现进程间简单通信,这里存在一个进程间同步问题,通俗来讲就是当一个进程写入数据后,另一个进程没有读取之前都被自己读取了,进程间的同步我们到后边总结,这里先简单实现两个进程间的通信。

/**********************************************************
*    > File Name: mkfifo-ser-1.c
*    > Author:xiao_k
*    > Mail:18629086235@163.com
*    > Created Time: Wed 21 Feb 2018 09:55:21 PM CST
**********************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<errno.h>#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>#define BUFSIZE 1024int main()
{char buf[BUFSIZE];int res = -1,fd = -1;res =  mkfifo("./testfifo",0777);if(-1 == res){perror("mkfifo ");exit(1);}fd = open("./testfifo",O_RDWR|O_EXCL);if(-1 == fd){perror("open");}while(1){printf("ser-> ");memset(buf,0,BUFSIZE);scanf("%s",buf);if(0 == strcmp(buf,"quit"))break;write(fd,buf,strlen(buf));sleep(2);read(fd,buf,BUFSIZE);printf("cli-> %s\n",buf);}if(open("./testfifo",O_EXCL) > 0 ){if(-1 == (res = unlink("./testfifo"))){perror("unlink");exit(1);}}else{perror("open ");exit(1);}return 0;
}/***********************************************************    > File Name: mkfifo-ser-1.c*    > Author:xiao_k*    > Mail:18629086235@163.com *    > Created Time: Wed 21 Feb 2018 09:55:21 PM CST**********************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<errno.h>#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>#define BUFSIZE 1024int main()
{char buf[BUFSIZE];int fd = -1,res= -1;fd = open("./testfifo",O_RDWR|O_EXCL);if(-1 == fd){perror("open");}while(1){memset(buf,0,BUFSIZE);read(fd,buf,BUFSIZE);printf("ser-> %s\n",buf);memset(buf,0,BUFSIZE);printf("cli->");scanf("%s",buf);if(0 == strcmp(buf,"quit"))break;write(fd,buf,strlen(buf));sleep(1);}if(open("./testfifo",O_EXCL) > 0 ){if(-1 == (res = unlink("./testfifo"))){perror("unlink");exit(1);}}else{perror("open ");exit(1);}return 0;
}

上边就是Linux通信的最基本的两种方式都只是做了最基本的举例,后几种我将分成专题分别总结,总结完了所有专题后,将综合运用。

转载于:https://blog.51cto.com/967243153/2072038

Linux系统编程之进程间通信相关推荐

  1. 【Linux系统编程】进程间通信之无名管道

    00. 目录 文章目录 00. 目录 01. 管道概述 02. 管道创建函数 03. 管道的特性 04. 管道设置非阻塞 05. 附录 01. 管道概述 管道也叫无名管道,它是是 UNIX 系统 IP ...

  2. 【Linux系统编程】进程间通信概述

    00. 目录 文章目录 00. 目录 01. 进程间通信概述 02. 进程间通信目的 03. 进程间通信机制 04. 附录 01. 进程间通信概述 进程是一个独立的资源分配单元,不同进程(这里所说的进 ...

  3. 【Linux系统编程】进程间通信--无名管道(pipe)

    管道的概述 管道也叫无名管道,它是是 UNIX 系统 IPC(进程间通信) 的最古老形式,所有的 UNIX 系统都支持这种通信机制. 无名管道有如下特点: 1.半双工,数据在同一时刻只能在一个方向上流 ...

  4. 【linux系统编程】进程间通信:信号中断处理

    什么是信号? 信号是 Linux 进程间通信的最古老的方式.信号是软件中断,它是在软件层次上对中断机制的一种模拟,是一种异步通信的方式 .信号可以导致一个正在运行的进程被另一个正在运行的异步进程中断, ...

  5. 【Linux系统编程】进程间通信之消息队列

    00. 目录 文章目录 00. 目录 01. 消息队列概述 02. 消息队列相关函数 03. 消息队列读写操作 04. 测试代码 05. 附录 01. 消息队列概述 消息队列提供了一种在两个不相关的进 ...

  6. 【Linux系统编程】进程间通信--消息队列

    概述 消息队列提供了一种在两个不相关的进程之间传递数据的简单高效的方法,其特点如下: 1)消息队列可以实现消息的随机查询.消息不一定要以先进先出的次序读取,编程时可以按消息的类型读取. 2)消息队列允 ...

  7. Linux系统编程之进程间通信(IPC)

    师承--陈立臣 文章目录 进程间通信分类 一.管道 1.无名管道 创建无名管道 2.命名管道(FIFO) 命名管道编程实战 二.消息队列 1.创建消息队列 三.共享内存 1.共享内存的创建 2.查看共 ...

  8. Linux系统编程(三) --进程间通信

    文章目录 1 进程间通信总览 1.1 进程间如何通信 1.2 Linux IPC 分类 1.3 Linux IPC常用手段 2 无名管道 2.1 pipe 函数 2.2 用pipe进行进程间通信 3 ...

  9. 【Linux系统编程】进程间通信之共享内存

    00. 目录 文章目录 00. 目录 01. 共享内存概述 02. 共享内存函数 2.1 创建共享内存 2.2 共享内存映射 2.3 共享内存解除映射 2.4 共享内存操作函数 03. 案例实战 04 ...

  10. 【Linux系统编程】进程间通信--共享内存

    概述 共享内存是进程间通信中最简单的方式之一.共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针.当一个进程改变了这块地址中的内容的时 ...

最新文章

  1. Ext.data-Store
  2. windows-台式机添加硬盘后如何加载、格式化新的分区
  3. MATLAB读取一张RGB图片转成YUV格式
  4. 删除共享内存_进程通信专题之 共享内存
  5. 怎么设置表头字体大小_Excel斜线表头和三线表头是如何制作的?
  6. char强制类型转换为int_为强制类型转换正名
  7. 【报告分享】2021年中国人工智能产业研究报告:数字经济时代的产业升级探索.pdf(附下载链接)...
  8. cmd命令java出错_Java基础知识_JavaSE_02
  9. 【论文写作】城市酒店入住信息管理系统中客房各项功能如何写
  10. 2020 年百度之星#183;程序设计大赛 - 初赛一
  11. 人工智能-10种机器学习常见算法
  12. W25Q64简介(译)
  13. 初学CODEBLOCK+wxWidgets
  14. 手机网站注册页面html模板,手机网页登录注册自适应模版
  15. Windows10安装JDK配置环境变量
  16. 上海车牌拍卖服务器响应时间,上海拍牌技巧:”48秒+700” 最晚出价为55秒
  17. 对电话号码进行格式校验、脱密、加密、解密、掩码等的操作介绍
  18. C-Cheating and Stealing_2021牛客暑期多校训练营5
  19. Softing物联网(IoT)方案之OT/IT数据集成
  20. 共享充电宝方案原理,具体部件组成以及主控MUC参数

热门文章

  1. Atitit机器学习原理与概论book attilax总结
  2. atitit。全局变量的设计与实现 java php的异同
  3. Atitit.404错误解决标准流程and url汉字中文路径404错误resin4 resin chinese char path 404 err解决
  4. atitit.科技公司的超级武器--超级框架,到底要不要自己的框架??
  5. paip.提升开发效率---增量备份项目文件
  6. 银行理财子公司的“超级”玩法
  7. SSH 协议端口号 22 背后的故事
  8. (转)首个比特币投资基金在加拿大获批上线!
  9. 2020年勒索病毒事件盘点及未来发展趋势
  10. 树立榜样、褒奖开源领域领袖人物、杰出贡献人物