管道

来源:互联网 发布:毛主 感谢日本 知乎 编辑:程序博客网 时间:2024/04/28 11:33

管道

管道:一个进程连接到另一个进程的一个数据流称为一个“管道”。
我们通常把是把一个进程的输出连接或“管接”(经过管道来连接)到另一个进程的输入。

作用:进程间通信

信号函数sigqueue()进程间只能传送int类型数据,管道可以传送任何数据。

匿名管道和有名管道:

匿名管道:1半双工,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道
                 2只能作用于有亲缘关系的。

有名管道:可以作用于不是亲缘关系的管道。
 

 

//******************************************匿名管道pipe()****************************************************
// 2013.10.20.
// 函数名:int pipe(int file_descriptor[2]);
// 功能:创建一无名管道
// 参数:file_descriptor:文件描述符数组,其中file_descriptor[0]表示读端,file_descriptor[1]表示写端*
// 返回值:成功返回0,失败返回错误代码
//******************************************匿名管道pipe()****************************************************
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
 int fd[2];      //定义一个文件描述符数组
 int pip = pipe(fd);    //将文件描述符放入管道
 if (pip == -1)
 {
  perror("Pipe Errpr!\n");
 }

 int pid = fork();
 if (pid > 0)
 {
  close(fd[0]);           //单双工,让它只能单端操作
  write(fd[1], "HelloWorld!\n", strlen("HelloWorld\n")); //fd[1]为管道的写入段,数据将会流入管道的另一端fd[0](另一进程)
 }
 else if (pid == 0)
 {
  close(fd[1]);           //单双工,让它只能单端操作
  char acBuf[1024];
  read(fd[0], acBuf, 1024);        //fd[0]为管道的读取端
  printf("Data : %s\n", acBuf);
 }
 else
 {
  perror("Fork error!");
  exit(1);
 }
 return 0;
}

//************************建立两个管道,让进程能够双向通信*********************************************************
int main()
{
 int fd[2];    //定义一个文件描述符数组
 pipe(fd);    //将文件描述符放入管道
 int fd1[2];    //再定义一个文件描述符数组用来搭建再一个管道
 pipe(fd1);
 
 int pid = fork();
 if (pid > 0)
 {
  char acBuf[1024];
  close(fd[0]);           //单双工,让它只能单端操作
  close(fd1[1]);
  write(fd[1], "HelloWorld!\n", strlen("HelloWorld\n")); //fd[1]为管道的写入段,数据将会流入管道的另一端fd[0](另一进程)
  
  sleep(3);
  read(fd1[0], acBuf, 1024);        
  printf("Data1 : %s\n", acBuf);
 }
 else if (pid == 0)
 {
  close(fd[1]);           //单双工,让它只能单端操作
  close(fd1[0]);
  char acBuf[1024];
  read(fd[0], acBuf, 1024);        //fd[0]为管道的读取端
  printf("Data : %s\n", acBuf);
  //fd1[1]为管道的写入段,数据将会流入管道的另一端fd1[0](另一进程)
  write(fd1[1], "Hi Good morning!\n", strlen("Hi Good morning!\n"));
 }
 else
 {
  perror("Fork error!");
  exit(1);
 }
 return 0;
}

 

 

/*******************************************************************************************************

下面有两端有名管道的代码

前面一段代码为读端
后面的代码为写端(一秒往有名管道里面写一个HelloWorld!)
编译后运行这两个文件,write后台运行,read前台运行
********************************************************************************************************/

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//******************************************有名管道****************************************************
// 2013.10.20.陈顺明
//创建
// 用shell命令创建"mkfifo + 管道名(如fifo)" prw-r--r--  1 root root    0 10-20 17:05 fifo(p开头为管道)
//也可以在程序中创建:int mkfifo(const char *filename,mode_t mode)

//有名管道作用:匿名管道只能作用于亲缘进程关系之间,有名管道不限于亲缘关系
//有名管道:可以理解为是一个文件,两个进程通过文件读取来中转数据(对它的操作和文件读写一样)
//******************************************有名管道****************************************************

int main()
{
 int fd = open("/ming/fifo", O_RDONLY);   //只写方式打开(只读或者只写方式打开,不能只读只写方式打开)
 if (fd < 0)
 {
  perror("Open Error!\n");
  exit(1);
 }
 while(1)
 {
  char  acBuf[1024] = {0};
  memset(acBuf, 0, 1024);
  int read_size = read(fd, acBuf, 1024);
  if (read_size > 0)
  {
   printf("Read Data: %s \n", acBuf);
  }

 }
 return 0;
}

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//******************************************有名管道****************************************************
// 2013.10.20.陈顺明
//创建
// 用shell命令创建"mkfifo + 管道名(如fifo)" prw-r--r--  1 root root    0 10-20 17:05 fifo(p开头为管道)
//也可以在程序中创建:int mkfifo(const char *filename,mode_t mode)

//有名管道作用:匿名管道只能作用于亲缘进程关系之间,有名管道不限于亲缘关系
//有名管道:可以理解为是一个文件,两个进程通过文件读取来中转数据(对它的操作和文件读写一样)
//******************************************有名管道****************************************************

int main()
{
 int fd = open("/ming/fifo", O_WRONLY);   //只写方式打开
 if (fd < 0)
 {
  perror("Open Error!\n");
  exit(1);
 }
 while(1)
 {
  write(fd, "HelloWorld!\n", strlen("HelloWorld!\n"));
  sleep(1);
 }
 return 0;
}

 

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//******************************************匿名管道pipe()****************************************************
// 2013.10.20.陈顺明
// int dup(int oldfd);    dup系统调用从头开始搜文件描述符数组,并且在找到第一个空闲文件描述符时完成它的复制
// int dup2(int oldfd, int newfd);    dup2系统调用复制操作之前,如果newfd已被打开,先关闭。
// int fcntl(int oldfd,F_DUPFD,int minifd)
//功能:复制文件描述符
//******************************************匿名管道pipe()****************************************************

//**************************************************dup()*****************************************************
int main()
{
 int fd = dup(1);          //文件描述符1为标准输出
 write(fd, "HelloWorld!\n", strlen("HelloWorld!\n")); //结果是打印"HelloWorld!"
 return 0;
}


//**************************************************Shell中运用管道"ls -al | wc"的实现*************************
int main()
{
 int fd[2];
 pipe(fd);
 int pid = fork();
 if (pid > 0)
 {
  close(0);       //关闭文件描述符0,让它成为第一个空闲文件描述符
  dup(fd[0]);       //找到第一个空闲文件描述符0(标准输入),完成它的复制
  
  close(fd[0]);
  close(fd[1]);
  execlp("wc", "wc", NULL);
 }
 else if(pid == 0)
 {
  close(1);
  dup(fd[1]);       //把文件描述符1(标准输出) *复制给fd[1]管道的写端*

  close(fd[0]);
  close(fd[1]);
  execlp("ls", "ls", "-al", NULL); //这条命令会在管道的写端进入留到另一进程的读端fd[0]
 }
 else
 {
  perror("Fork Error!\n");
  exit(1);
 }
 return 0;
}

//**************************************************dup2()*****************************************************
int main()
{
 int fd = open("/ming/myfile1", O_RDWR | O_CREAT , S_IRWXU);
 if (fd < 0)
 {
  perror("Open Error!\n");
  exit(1);
 }

 dup2(1, fd);      //把1复制给fd(是哟dup2会先把之前的fd关闭再把1复制给它)
 write(fd, "Hi ChenShunMing!\n", strlen("Hi ChenShunMing!\n"));
 return 0;
}

 

//******************************************popen()****************************************************
// 2013.10.20.陈顺明
// FILE* popen(const char *command, const char *open_mode)
// 功能 :允许一个程序把另外一个程序当作一个新的进程来启动,并能对它发送数据或接收数据
// command:待运行程序的名字和相应的参数
// open_mode:必须是“r(返回的指针是给用户读的)”或“w(返回的指针是要用户往里写的)”
// 如果操作失败,popen会返回一个空指针
//******************************************popen()****************************************************

//****************************用popen()实现管道"ls -al | wc"功能

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
 FILE *rFile = popen("ls -al", "r"); //把结果写到rFile文件里面
 char acBuf[1024];
 fread(acBuf, 1, 1024, rFile);  //读文件
// printf("Read Data : %s", acBuf);
 pclose(rFile);      //用popen打开的用pclose关闭

 FILE *wFile = popen("wc", "w");  //需要往wFile文件里面写数据
 fwrite(acBuf, 1, strlen(acBuf), wFile);
 pclose(wFile);

 return 0;
}

 

 

原创粉丝点击