一、管道

管道:管道是一种半双工的通信方式,数据只能单方向流动,而且只能在具有亲缘关系的进程间使用,因为管道

传递数据的单向性,管道又称为半双工管道。进程的亲缘关系通常是指父子进程关系。

管道的特点决定了其使用的局限性:

  • 数据只能由一个进程流向另一个进程(其中一个为写管道,另一个为读管道);如果要进行全双工通信,需要

建立两个管道。

  • 管道只能用于父子进程或者兄弟进程间的通信,也就是说管道只能用于具有亲缘关系的进程间的通信,无亲缘

关系的进程不能使用管道。

管道的创建:

Linux下创建管道可以通过函数pipe来完成。该函数如果调用成功则返回0,并且数组中将包含两个新的文件描述符;

如果有错误发生,返回-1,该函数返回两个文件描述符:pipefd[0]和pipefd[1]。前者打开来读,后者打开来写。该函

数的原型为:

#include <fcntl.h>

#include <unistd.h>

int pipe(int pipefd[2]);

1. 下面是通过建立管道和创建父子进程间的通信:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/wait.h> int main()
{
int fd[];
pid_t pid;
int ret;
ret= pipe(fd);
if(ret== -)
{
perror("pipe.\n");
exit();
}
pid= fork();
if(pid== -)
{
perror("fork.\n");
exit();
}
else if(pid== )
{
char buff[];
close(fd[]);
read(fd[],buff,);
printf("Form parent say: %s\n",buff);
close(fd[]);
}
else
{
char *say= "Hello Linux.";
close(fd[]);
write(fd[],say,strlen(say)+ );
close(fd[]);
int status;
wait(&status);
}
return ;
}

这是父子进程间利用管道进行通信的一个例子。

2. 下面是通过建立两个管道来实现父子进程间全双工通信:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/wait.h> int main()
{
char *parent_talk[]= {"Hello","Can you tell me what time is it?","Ok,I must go,Bye",NULL};
char *child_talk[]= {"Hi","No problem","See you,Bye",NULL};
int fd1[],fd2[];
pid_t pid;
int ret;
ret= pipe(fd1);
if(ret== -)
{
perror("pipe1.\n");
exit();
}
ret= pipe(fd2);
if(ret== -)
{
perror("pipe2.\n");
exit();
}
pid= fork();
if(pid== -)
{
perror("fork.\n");
exit();
}
else if(pid== )
{
char buff[];
close(fd1[]);
close(fd2[]);
int i= ;
char *talk= child_talk[i];
while(talk!= NULL)
{
read(fd1[],buff,);
printf("Parent say: %s\n",buff);
write(fd2[],talk,strlen(talk)+ );
talk= child_talk[++i];
}
close(fd1[]);
close(fd2[]);
}
else
{
char buff[];
close(fd1[]);
close(fd2[]);
int i= ;
char *talk= parent_talk[i];
while(talk!= NULL)
{
write(fd1[],talk,strlen(talk)+ );
read(fd2[],buff,);
printf("Child say: %s\n",buff);
talk= parent_talk[++i];
}
close(fd1[]);
close(fd2[]);
int status;
wait(&status);
}
return ;
}

这是通过建立两个管道来实现父子进程间全双工通信的例子。

二、有名管道

管道的有一个不足之处是没有名字,因此,只能用于具有亲缘关系的进程间通信,在有名管道(FIFO)提出后,该

限制得到了克服。FIFO不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存储于文件系统中。有名

管道是一个设备文件,因此,即使进程与创建FIFO的进程不存在亲缘关系,只要可以访问该路径,就能够通过FIFO相

互通信。需要注意的是,FIFO总是按照先进先出的原则工作,第一个被写入的数据将首先从管道中读出。

有名管道的创建:

Linux下有两种方式创建有名管道。一是在Shell下交互地建立一个有名管道,二是在程序中使用系统函数建立有

名管道。Shell方式下可使用mkfifo或mknod命令。创建有名管道的系统函数有两个:mkfifo和mknod。两个函数均定义

在头文件sys/stat.h中,函数的原型为:

#include <sys/types.h>
    #include <sys/stat.h>
    int mkfifo(const char *pathname,mode_t mode);

int mknod(const char *pathname,mode_t mode,dev_t dev);

函数mkfifo参数中pathname为创建的有名管道的全路径名;mode为创建的有名管道的模式,指明其存取权限;函

数mknod参数中pathname为创建的有名管道的全路径名;mode为创建的有名管道的模式,指明其存取权限;dev为设

备值,该值取决于文件创建的种类,它只在创建设备文件时才会用到。这两个函数调用成功都返回0,失败都返回-1。

下面是使用有名管道建立一个客户端/服务器的例子:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/wait.h>
#define BUFFER_SIZE 256
const char *write_fifo= "write_fifo";
const char *read_fifo= "read_fifo"; int main()
{
if(access(write_fifo,F_OK))
{
int ret= mkfifo(write_fifo,);
if(ret== -)
{
perror("mkfifo");
exit();
}
}
int write_fd= open(write_fifo,O_WRONLY);
if(write_fd== -)
{
perror("open write_fifo.");
exit();
}
int read_fd;
while()
{
read_fd= open(read_fifo,O_RDONLY);
if(read_fd== -)
{
sleep();
continue;
}
break;
}
char sendbuf[BUFFER_SIZE];
char recvbuf[BUFFER_SIZE];
while()
{
printf("Ser:");
scanf("%s",sendbuf);
if(strcmp(sendbuf,"quit")== )
{
unlink(write_fifo);
break;
}
write(write_fd,sendbuf,strlen(sendbuf)+ );
read(read_fd,recvbuf,BUFFER_SIZE);
printf("Cli:%s\n",recvbuf);
}
close(write_fd);
close(read_fd);
return ;
}
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/wait.h>
#define BUFFER_SIZE 256
const char *write_fifo= "write_fifo";
const char *read_fifo= "read_fifo"; int main()
{
int read_fd= open(write_fifo,O_RDONLY);
if(read_fd== -)
{
perror("open write_fifio.");
exit();
}
if(access(read_fifo,F_OK))
{
int ret= mkfifo(read_fifo,);
if(ret== -)
{
perror("mkfifo");
exit();
}
}
int write_fd= open(read_fifo,O_WRONLY);
if(write_fd== -)
{
perror("open read_fifo.");
exit();
}
char sendbuf[BUFFER_SIZE];
char recvbuf[BUFFER_SIZE];
while()
{
read(read_fd,recvbuf,BUFFER_SIZE);
printf("Ser:%s\n",recvbuf);
printf("Cli:");
scanf("%s",sendbuf);
if(strcmp(sendbuf,"quit")== )
{
unlink(read_fifo);
break;
}
write(write_fd,sendbuf,strlen(sendbuf)+ );
}
close(write_fd);
close(read_fd);
return ;
}

                                         

Linux进程间通信---管道和有名管道的更多相关文章

  1. Unix/Linux进程间通信(二):匿名管道、有名管道 pipe()、mkfifo()

    1. 管道概述及相关API应用 1.1 管道相关的关键概念 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: 管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管 ...

  2. Linux 进程通信(有名管道)

    有名管道(FIFO) 有名管道是持久稳定的. 它们存在于文件系统中. FIFO比无名管道作用更大,因为他们能让无关联的进程之间交换数据. 管道文件一般用于交换数据. shell命令创建管道 一个she ...

  3. Linux进程间通信方式--信号,管道,消息队列,信号量,共享内存

    1.概述 通信方法 无法介于内核态与用户态的原因 管道(不包括命名管道) 局限于父子进程间的通信. 消息队列 在硬.软中断中无法无阻塞地接收数据. 信号量 无法介于内核态和用户态使用. 内存共享 需要 ...

  4. UNIX环境高级编程——无名管道和有名管道

    一.进程间通信 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2 ...

  5. linux进程间通信之一:无名管道

    无名管道是linux中管道通信的一种原始方法,有以下特征: 1.单工通信模式,具有固定的读端和写端: 2.管道可以看成是一种特殊的文件,对于它的读写可以使用普通的read(),write()等文件IO ...

  6. Linux系统编程(11)——进程间通信之有名管道

    管道应用的一个重大限制是它没有名字,因此,只能用于具有亲缘关系的进程间通信,在有名管道(named pipe或FIFO)提出后,该限制得到了克服.FIFO不同于管道之处在于它提供一个路径名与之关联,以 ...

  7. Linux 进程间通信 有名管道(fifo)

    有名管道特点: 1)无名管道只能用于具有亲缘关系的进程之间,这就限制了无名管道的使用范围 2)有名管道可以使互不相关的两个进程互相通信. 3)有名管道可以通过路径名来指出,并且在文件系统中可见,但内容 ...

  8. Linux进程间通信之管道

    1,进程间通信 (IPC ) Inter-Process Communication 比较好理解概念的就是进程间通信就是在不同进程之间传播或交换信息. 2,linux下IPC机制的分类:管道.信号.共 ...

  9. Linux环境进程间通信(一):管道及命名管道

    linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...

随机推荐

  1. Android仿QQ界面

    最近这几天,一直跟着朋友们聚会什么的,没怎么做项目,今天总算是有时间开电脑继续做我的项目了.下面我就把我做的效果展示一下. 这是模仿了qq的界面效果.因为代码比较长就不粘贴代码了.需要的小伙伴可以跟我 ...

  2. mac上如何卸载node

    homebrew安装的 直接一条命令 brew uninstall node 官网下载pkg安装包的 一条命令 sudo rm -rf /usr/local/{bin/{node,npm},lib/n ...

  3. 使用 Python 设置数据的路径

    使用 Python 设置数据的路径 编程语言(如 Python)将反斜线 (\) 用作转义字符.例如,\n 表示换行符,\t 表示制表符.指定路径时,可使用正斜线 (/) 代替反斜线.使用两条反斜线( ...

  4. python 动态导入模块、断言

    断言: 类似与判断,后面的程序依赖前面的,可以加一个断言,断言成功继续执行.断言失败报错停止执行. a = 'abc' assert type(a) is str print('yes') asser ...

  5. tomcat、Apache服务器外网无法访问80和8080端口,其他端口可以访问

    tomcat.Apache服务器外网无法访问80和8080端口,其他端口都可以访问,很明显地看出这是网络运营商的问题,他们把80和8080端口对外访问屏蔽了. 解释:这两个端口是常用的HTTP协议端口 ...

  6. IIS中X509Certificate遇见的问题

    由于开发过程中需要用到证书,所以通过调用 X509Certificate2 访问p12文件. 代码开发完成后,在本地VS上测试通过,本地IIS上测试通过,发布到线上服务器IIS后不通过:提示找不到文件 ...

  7. thrift基本概念和实例

    一.thrift可以做什么 thrift是一个跨语言通信的工具,支持的语言多,而且还提供服务器端的众多网络模型,使服务端的开发可以只专于服务本身的逻辑. 二.thrift重要概念 1.processo ...

  8. datatable Left and right fixed columns

    $(document).ready(function() { var table = $('#example').DataTable( { scrollY: "300px", sc ...

  9. PythonTip(1)

    发现一个Python的题库,嘿嘿,练练手吧~~~ http://www.pythontip.com/ a + b 描述: 给你两个数a.b,请你计算它们的和,并输出. 例如: a = 3, b = 2 ...

  10. LA 3126 出租车

    题目链接:https://vjudge.net/problem/UVALive-3126 题意:有m个客人,位于不同的位置,去一些地方,出发的时间给出,要一些出租车去接,但是,每辆出租车要在出发前一分 ...