百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 优雅编程 > 正文

进程间通信(一)—管道

sinye56 2024-11-24 21:29 10 浏览 0 评论

我会用几篇博客总结一下在Linux中进程之间通信的几种方法,我会把这个开头的摘要部分在这个系列的每篇博客中都打出来

进程之间通信的方式

  • 管道
  • 消息队列
  • 信号
  • 信号量
  • 共享存储区
  • 套接字(socket)

在以一切皆文件为原则的Linux系统中,管道也是一种文件(特殊文件),可以使用mkfifo命令创建一个管道文件

在管道文件的前面有一个p来标识管道文件

这次主要说的是通过管道完成进程之间的通信,通过管道通信有两种方式。

一种是匿名管道,一种是命名管道

先来看一段代码

 1 #define MAXLINE 80
 2 int main
 3 {
 4     int n;
 5     int fd[2];
 6     pid_t pid;
 7     char line[MAXLINE];
 8     if (pipe(fd) < 0)
 9         perror("pipe");
10     if ((pid = fork) < 0)
11         perror("fork");
12     if (pid > 0)
13     {
14         //father
15         close(fd[0]);
16 } 17 else 18 { 19close(fd[1]);
20 n = read(fd[0], line, MAXLINE); 21 write(stdout, line, n);//写到标准输出上看一下效果 22 } 23 return 0; 24 25 }

这个程序就是一个简单的父子进程之间通过管道进行通信的一个例子,具体的工作过程我用画图的方式展现出来

注意这一个步骤是十分重要的,如果不关闭相应的端口,就无法正确操作管道。

匿名管道主要利用了,创建子进程的时候会把父进程的文件描述符表拷贝一份这个特征,通过这个特征,父子进程就看到了一个公共的资源—管道,并同时拥有对该管道腹泻的权利,那么一方读,一方写,就可以完成进程之间的通信了。

所谓的匿名管道就是说,没有名字。。。你根本不知道这个管道文件存放在哪,也不知道这个管道文件的文件名,唯一跟这个跟管道文件有联系的只有父子进程中的文件描述符。那么根据匿名管道的实现机制,很容易就能看出他的优缺点。

  • 管道的n个特征
    • 管道是依赖于文件系统的,创建好管道之后,一定要关闭不使用的读写端
    • 只有父子进程才可以使用管道通信,也就是所谓的有血缘关系的进程进行进程间通信。(匿名管道独有)
    • 管道是基于数据流的,面向字节流!(后面会提到消息队列是面向数据块的,对比来看会好懂一些)
    • 管道只能称之为单向数据通信,连半双工都算不上
    • 同步与互斥问题不需要考虑了,管道已经考虑了
    • 当父子进程退出的时候,管道的生命周期就结束了,也就是说管道的生命周期就是进程

上述就是匿名管道的使用和实现机制,可以看出必须有“亲缘关系”的进程之间才可以使用匿名管道来完成进程间通信。父子进程当然可以,“孙子”进程也是可以的~

那么为了解决只有有亲缘关系的进程才能使用这种方式进行通信的弊端,就有了命名管道的通信方式

简单的来说,我们刚才使用的匿名管道是因为不知道文件名和存放路径,所以只能通过继承文件描述符表来获得跟匿名管道建立联系的方式,如果我们知道路径和管道文件名呢?那不就可以完成非亲缘关系的进程间通信了么

  • 函数原型 int mkfifo(const char *pathname,mode_t mode)
  • 其中第一个参数pathname就是路径了,mode 就是创建的管道的访问权限umask
  • 头文件:#include <sys.stat.h> #include <sys/types.h>
  • 返回值,成功返回0,失败返回-1

下面贴上代码

这个是server的

    1 #include <sys/types.h> 
    2 #include <sys/stat.h> 
    3 #include <stdio.h> 
    4 #include <unistd.h> 
    5 #include <stdlib.h> 
    6 #include <errno.h> 
    7 #include <string.h> 
    8 #include <fcntl.h> 
    9 #define _PATH_NAME_ "./pp" 
   10 
   11 int main 
   12 { 
>> 13   char *str="hello world"; 
   14   int fd; 
   15   if(mkfifo(_PATH_NAME_,0644)<0)· 
   16   { 
   17     printf("hahaha\n"); 
   18     printf("mkfifo error %d:%s\n",errno,strerror(errno)); 
   19   } 
   20   fd=open(_PATH_NAME_,O_WRONLY); 
   21   write(fd,str,strlen(str)); 
   22   return 0; 
   23 } 

这个是client的

  2 #include <sys/types.h>
  3 #include <sys/stat.h>
  4 #include <stdio.h>
  5 #include <unistd.h>
  6 #include <stdlib.h>
  7 #include <errno.h>
  8 #include <string.h>
  9 #include <fcntl.h>
 10    
 11 #define _PATH_NAME_ "./pp"
 12    
 13    
 14 int main
 15 {  
 16   int fd;
 17   fd=open(_PATH_NAME_,O_RDONLY); 
 18   char buf[1024]={'\0'};
 19   read(fd,buf,1024);
 20   printf("%s\n",buf);
 21   return 0;
 22 }  

可以通过open函数来打开分别使用read和write函数来读写管道,当然也可以close掉标准输入输出,做成重定向的那样也是可以的

那么管道有多大呢,我们可以往里面扔多少数据呢?

既然管道也是一个文件,那么肯定有大小上限,这也是其一个缺点,大小有限的,那么我们究竟可以写多少数据放进管道呢,使用man 7 pipe命令打开pipe的说明文档,可以看见这么一段

Pipe capacity

A pipe has a limited capacity. If the pipe is full, then a write(2)

will block or fail, depending on whether the O_NONBLOCK flag is set

(see below). Different implementations have different limits for the

pipe capacity. Applications should not rely on a particular capacity:

an application should be designed so that a reading process consumes

data as soon as it is available, so that a writing process does not

remain blocked.

In Linux versions before 2.6.11, the capacity of a pipe was the same as

the system page size (e.g., 4096 bytes on i386). Since Linux 2.6.11,

the pipe capacity is 65536 bytes.

看,我现在的版本是2.6.11之后了,所以是65536字节,之间的版本就是4096字节

最后的最后,来一个管道最大的缺点,管道是基于文件系统的!所以不管是读还是写,都要求访问磁盘进行I/O操作,I/O的速度你懂得,特别慢,所以不适合做多个client的结构,不然会很慢

相关推荐

程序员:JDK的安装与配置(完整版)_jdk的安装方法

对于Java程序员来说,jdk是必不陌生的一个词。但怎么安装配置jdk,对新手来说确实头疼的一件事情。我这里以jdk10为例,详细的说明讲解了jdk的安装和配置,如果有不明白的小伙伴可以评论区留言哦下...

Linux中安装jdk并配置环境变量_linux jdk安装教程及环境变量配置

一、通过连接工具登录到Linux(我这里使用的Centos7.6版本)服务器连接工具有很多我就不一一介绍了今天使用比较常用的XShell工具登录成功如下:二、上传jdk安装包到Linux服务器jdk...

麒麟系统安装JAVA JDK教程_麒麟系统配置jdk

检查检查系统是否自带java在麒麟系统桌面空白处,右键“在终端打开”,打开shell对话框输入:java–version查看是否自带java及版本如图所示,系统自带OpenJDK,要先卸载自带JDK...

学习笔记-Linux JDK - 安装&amp;配置

前提条件#检查是否存在JDKrpm-qa|grepjava#删除现存JDKyum-yremovejava*安装OracleJDK不分系统#进入安装文件目...

Linux新手入门系列:Linux下jdk安装配置

本系列文章是把作者刚接触和学习Linux时候的实操记录分享出来,内容主要包括Linux入门的一些理论概念知识、Web程序、mysql数据库的简单安装部署,希望能够帮到一些初学者,少走一些弯路。注意:L...

测试员必备:Linux下安装JDK 1.8你必须知道的那些事

1.简介在Oracle收购Sun后,Java的一系列产品就被整合到Oracle官网中,打开官网乍眼一看也不知道去哪里下载,还得一个一个的摸索尝试,而且网上大多数都是一些Oracle收购Sun前,或者就...

Linux 下安装JDK17_linux 安装jdk1.8 yum

一、安装环境操作系统:JDK版本:17二、安装步骤第一步:下载安装包下载Linux环境下的jdk1.8,请去官网(https://www.oracle.com/java/technologies/do...

在Ubuntu系统中安装JDK 17并配置环境变量教程

在Ubuntu系统上安装JDK17并配置环境变量是Java开发环境搭建的重要步骤。JDK17是Oracle提供的长期支持版本,广泛用于开发Java应用程序。以下是详细的步骤,帮助你在Ubuntu系...

如何在 Linux 上安装 Java_linux安装java的步骤

在桌面上拥抱Java应用程序,然后在所有桌面上运行它们。--SethKenlon(作者)无论你运行的是哪种操作系统,通常都有几种安装应用程序的方法。有时你可能会在应用程序商店中找到一个应用程序...

Windows和Linux环境下的JDK安装教程

JavaDevelopmentKit(简称JDK),是Java开发的核心工具包,提供了Java应用程序的编译、运行和开发所需的各类工具和类库。它包括了JRE(JavaRuntimeEnviro...

linux安装jdk_linux安装jdk软连接

JDK是啥就不用多介绍了哈,外行的人也不会进来看我的博文。依然记得读大学那会,第一次实验课就是在机房安装jdk,编写HelloWorld程序。时光飞逝啊,一下过了十多年了,挣了不少钱,买了跑车,娶了富...

linux安装jdk,全局配置,不同用户不同jdk

jdk1.8安装包链接:https://pan.baidu.com/s/14qBrh6ZpLK04QS8ogCepwg提取码:09zs上传文件解压tar-zxvfjdk-8u152-linux-...

运维大神教你在linux下安装jdk8_linux安装jdk1.7

1.到官网下载适合自己机器的版本。楼主下载的是jdk-8u66-linux-i586.tar.gzhttp://www.oracle.com/technetwork/java/javase/downl...

window和linux安装JDK1.8_linux 安装jdk1.8.tar

Windows安装JDK1.8的步骤:步骤1:下载JDK打开浏览器,找到JDK下载页面https://d.injdk.cn/download/oraclejdk/8在页面中找到并点击“下载...

最全的linux下安装JavaJDK的教程(图文详解)不会安装你来打我?

默认已经有了linux服务器,且有root账号首先检查一下是否已经安装过java的jdk任意位置输入命令:whichjava像我这个已经安装过了,就会提示在哪个位置,你的肯定是找不到。一般我们在...

取消回复欢迎 发表评论: