Linux进程间通信--管道

       进程间通信是指两个不同进程间可以交换数据,因此操作系统应提供两个进程可以同时访问的内存空间。

普通管道(PIPE)
       为了完成进程间通信,需要创建管道,管道不属于进程的资源,而是和套接字一样属于操作系统。因此两个进程通过操作系统提供的内存空间进行通信。下面是创建管道的函数:

#include<unistd.h>
int pipe(int filedes[2]);
//成功时返回0,失败时返回-1
  • filedes[0]---通过管道接收数据时使用的文件描述符,即管道出口
  • filedes[1]---通过管道传输数据时使用的文件描述符,即管道入口

父进程与子进程数据交换示例:

#include<stdio.h>
#include<unistd.h>
#define BUF_SIZE 30

int main()
{
   int fds[2];
   char str[]="Who are you?";
   char buf[BUF_SIZE];
   pid_t pid;
   
   pipe(fds);//pipe创建管道
   pid=fork();
   if(pid==0)
   {
      write(fds[1],str,sizeof(str));//子进程向管道传递字符串   
   }else{
      read(fds[0],buf,BUF_SIZE);  //父进程从管道接收字符串
      puts(buf);
   }
   return 0;
}

下面通过一个管道进行双向通信:

#include<stdio.h>
#include<unistd.h>
#define BUF_SIZE 30

int main(int argc,char *argv[])
{
   int fds[2];
   char str1[]="Who are you?"; 
   char str2[]="Thank you for your message";
   char buf[BUF_SIZE];
   pid_t pid;
   
   pipe(fds);
   pid=fork();
   if(pid==0){
      write(fds[1],str1,sizeof(str1));
      sleep(2);
      read(fds[0],buf,BUF_SIZE);
      printf("Child proc output:%s \n",buf);
   }
   else{
      read(fds[0],buf,BUF_SIZE);
      printf("Parent proc output:%s \n",buf);
      write(fds[1],str2,sizeof(str2));
      sleep(3);
   }
   return 0;
} 

        向管道传递数据时,先读的进程会把数据取走。数据进入管道后成为无主数据,通过read函数先读取数据的进程将得到数据,即使该进程将数据传到了管道。因此子进程中代码sleep(2)是关键,如果没有,子进程将读回自己向管道发送的数据,结果父进程调用read函数后将无限期等待数据进入管道。
        因此在进行双向通信时可以创建两个管道,各自负责不同的数据流,如下面示例所示:

#include<stdio.h>
#include<unistd.h>
#define BUF_SIZE 30

int main(int argc,char *argv[])
{
   int fds1[2],fds2[2];
   char str1[]="Who are you?";
   char str2[]="Thank you for your message";
   char buf[BUF_SIZE];
   pid_t pid;
   
   pipe(fds1),pipe(fds2);
   pid=fork();
   if(pid==0){
      write(fds1[1],str1,sizeof(str1));
      read(fds2[0],buf,BUF_SIZE);
      printf("Child proc output:%s \n",buf);
   }
   else{
      read(fds1[0],buf,BUF_SIZE);
      printf("Parent proc output:%s \n",buf);
      write(fds[2],str2,sizeof(str2));
      sleep(3);
   }
   return 0;
}

命名管道(FIFO)
       通常的管道只能连接相关的进程,使用命名管道可以连接不相关的进程,并且可以独立于进程存在。称这样的命名管道为FIFO(先进先出队列)。
创建FIFO

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

使用指定的权限模式来创建FIFO。mkfifo命令通常调用这个函数

删除FIFO

#include<sys/types.h>
void unlink(char *filoname);

此函数可以用来删除FIFO

监听FIFO的连接

#include<sys/types.h>
int open(char *filoname,O_RDONLY);

open函数阻塞进程直到某一进程打开FIFO进行写操作

通过FIFO会话

#include<sys/types.h>
int open(char *filename,O_WRONLY)

open函数阻塞进程直到某一进程打开FIFO进行读取操作。

两进程通过FIFO进行通信
发送进程用write调用,而监听进程使用read调用。写进程调用close来通知读进程通信结束。

下面两个shell脚本是基于FIFO的时间/日期服务的服务器和客户端程序:

#!/bin/sh
# time server
    while true;do
       rm -f /tmp/time_fifo
       mkfifo /tmp/time_fifo
       date> /tmp/time_fifo
    done

 

#! /bin/sh
# time client
  cat /tmp/time_fifo

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值