进程间通讯(一)—管道

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

进程之间通讯的方式app

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

进程间通讯(二)—消息队列传送门:http://www.cnblogs.com/lenomirei/p/5642575.htmlsocket

进程间通讯(三)—信号量传送门:http://www.cnblogs.com/lenomirei/p/5649792.html函数

进程间通讯(四)—共享存储区传送门:http://www.cnblogs.com/lenomirei/p/5651995.htmlspa

进程间通讯(五)—信号传送门:http://www.cnblogs.com/lenomirei/p/5656449.htmlcode

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

 

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

 

此次主要说的是经过管道完成进程之间的通讯,经过管道通讯有两种方式。blog

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

 

  • 匿名管道


先来看一段代码

 

 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  { 19         close(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)<016 { 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的结构,否则会很慢

相关文章
相关标签/搜索