⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pipes.html.txt

📁 LINUX进程通信的学习资料
💻 TXT
字号:
Interprocess?Communication?(IPC)和管道Pipes? 

  在UNIX的内核环境中,要解决的一个首要问题是:如何控制和处理不同进程之间的通信和数据交换。 
本章中我们将通过研究一个简单的实例,看看在同一台机器的UNIX环境下多个进程是如何运行和被我们控制的 
(使用fork()方法)。? 
  能够实现进程间通信的方法有: 
  ·?Pipes? 
  ·?Signals? 
  ·?Message?Queues? 
  ·?Semaphores? 
  ·?Shared?Memory? 
  ·?Sockets? 
  本文先学习如何使用Pipes?方法来实现两个进程间的通信,而其它进程间通信的方法我们将在接下来的文章 
中详细讨论。 
  在UNIX环境下可以使用两种方式打开一个管道:Formatted?Piping方式和Low?Level?Piping方式。? 

1.1?popen()?--?Formatted?Piping? 

  FILE?*popen(char?*command,?char?*type) 
  描述了打开一个I/O管道的方法。 
  其中command参数描述创建管道的进程,type参数描述了管道打开的类型:"r"表示以读方式打开,"w"表示以 
写方式打开。 
  popen()的返回值是一个指针流或NULL指针(出现错误时)。 
  使用popen()方法打开的管道,在使用完毕后必须用pclose(FILE?*stream)方法关闭。 

  用户界面可以通过fprintf()和fscanf()方法来实现和管道的通信。 

1.2?pipe()?--?Low?level?Piping? 

  int?pipe(int?fd[2])? 
  将创建一个管道和两个文件描述符:fd[0],?fd[1]。 
  其中fd[0]?文件描述符将用于读操作,而fd[1]?文件描述符将用于写操作。? 
  pipe()的成功返回值是0,如果创建失败将返回-1并将失败原因记录在errno中。? 
  使用int?pipe(int?fd[2])创建管道的标准编程模式如下: 
  1)?创建管道; 
  2)?使用fork(?)方法创建两个(或多个)相关联的进程; 
  3)?使用read()和write()方法操作管道; 
  4)?管道使用完毕后用close(int?fd)方法关闭管道。 

  下一段程序中使用了该种Low?Level?Piping的方法,实现了父进程对子进程的写操作: 

  int?pdes[2]; 
  pipe(pdes); 
  if?(?fork()?==?0?) 
  {/*?child?*/ 
  close(pdes[1]);?/*?not?required?*/ 
  read(?pdes[0]);?/*?read?from?parent?*/ 
  ..... 
  } 
  else 
  {?close(pdes[0]);?/*?not?required?*/ 
  write(?pdes[1]);?/*?write?to?child?*/ 
  ..... 
  } 

1.4?应用实例分析 

  本节提供了一个完整的管道应用实例,其结构说明如下:? 
  1)?实例含有两个程序模块plot.c?(主程序)和plotter.c;? 
  2)?程序运行在Solaris2.6环境下并必须预先安装了GNU的免费画图软件gnuplot?在以下目录:/usr/local/bin/; 
  3)?程序plot.c调用gnuplot;? 
  4)?Plot将产生两个数据流:? 
  y?=?sin(x)? 
  y?=?sin(1/x)? 
  5)?程序将创建两个管道:每个数据流对应一个管道。 
  本实例在Solaris2.6的UNIX环境下调试通过。 

plot.c程序的源代码如下: 
/*?plot.c?-?example?of?unix?pipe.?Calls?gnuplot?graph?drawing?package?to?draw 
graphs?from?within?a?C?program.?Info?is?piped?to?gnuplot?*/ 
/*?Creates?2?pipes?one?will?draw?graphs?of?y=0.5?and?y?=?random?0-1.0?*/ 
/*?the?other?graphs?of?y?=?sin?(1/x)?and?y?=?sin?x?*/ 

/*?Also?user?a?plotter.c?module?*/ 
/*?compile:?cc?-o?plot?plot.c?plotter.c?*/ 

#include?"externals.h" 
#include? 
#define?DEG_TO_RAD(x)?(x*180/M_PI) 

double?drand48(); 
void?quit(); 
FILE?*fp1,?*fp2,?*fp3,?*fp4,?*fopen(); 

main() 
{?float?i; 
float?y1,y2,y3,y4; 

/*?open?files?which?will?store?plot?data?*/ 
if?(?((fp1?=?fopen("plot11.dat","w"))?==?NULL)?|| 
((fp2?=?fopen("plot12.dat","w"))?==?NULL)?|| 
((fp3?=?fopen("plot21.dat","w"))?==?NULL)?|| 
((fp4?=?fopen("plot22.dat","w"))?==?NULL)?) 
{?printf("Error?can't?open?one?or?more?data?files\n"); 
exit(1); 
} 

signal(SIGINT,quit);?/*?trap?ctrl-c?call?quit?fn?*/ 
StartPlot(); 
y1?=?0.5; 
srand48(1);?/*?set?seed?*/ 
for?(i=0;;i+=0.01)?/*?increment?i?forever?use?ctrl-c?to?quit?prog?*/ 
{?y2?=?(float)?drand48(); 
if?(i?==?0.0) 
y3?=?0.0; 
else 
y3?=?sin(DEG_TO_RAD(1.0/i)); 
y4?=?sin(DEG_TO_RAD(i)); 

/*?load?files?*/ 
fprintf(fp1,"%f?%f\n",i,y1); 
fprintf(fp2,"%f?%f\n",i,y2); 
fprintf(fp3,"%f?%f\n",i,y3); 
fprintf(fp4,"%f?%f\n",i,y4); 
/*?make?sure?buffers?flushed?so?that?gnuplot?*/ 
/*?reads?up?to?data?file?*/? 
fflush(fp1); 
fflush(fp2); 
fflush(fp3); 
fflush(fp4); 

/*?plot?graph?*/ 
PlotOne(); 
usleep(250);?/*?sleep?for?short?time?*/ 
} 
} 

void?quit() 
{?printf("\nctrl-c?caught:\n?Shutting?down?pipes\n"); 
StopPlot(); 

printf("closing?data?files\n"); 
fclose(fp1); 
fclose(fp2); 
fclose(fp3); 
fclose(fp4); 
printf("deleting?data?files\n"); 
RemoveDat(); 
} 
The?plotter.c?module?is?as?follows:? 
/*?plotter.c?module?*/ 
/*?contains?routines?to?plot?a?data?file?produced?by?another?program?*/ 
/*?2d?data?plotted?in?this?version?*/ 
/**********************************************************************/ 
#include?"externals.h" 

static?FILE?*plot1, 
*plot2, 
*ashell; 

static?char?*startplot1?=?"plot?[]?[0:1.1]'plot11.dat'?with?lines,? 
'plot12.dat'?with?lines\n"; 
static?char?*startplot2?=?"plot?'plot21.dat'?with?lines,? 
'plot22.dat'?with?lines\n"; 
static?char?*replot?=?"replot\n"; 
static?char?*command1=?"/usr/local/bin/gnuplot>?dump1"; 
static?char?*command2=?"/usr/local/bin/gnuplot>?dump2"; 
static?char?*deletefiles?=?"rm?plot11.dat?plot12.dat?plot21.dat?plot22.dat"; 
static?char?*set_term?=?"set?terminal?x11\n"; 

void 
StartPlot(void) 
{?plot1?=?popen(command1,?"w"); 
fprintf(plot1,?"%s",?set_term); 
fflush(plot1); 
if?(plot1?==?NULL) 
exit(2); 
plot2?=?popen(command2,?"w"); 
fprintf(plot2,?"%s",?set_term); 
fflush(plot2); 
if?(plot2?==?NULL) 
exit(2); 
} 
void? 
RemoveDat(void) 
{?ashell?=?popen(deletefiles,?"w"); 
exit(0); 
} 
void 
StopPlot(void) 
{?pclose(plot1); 
pclose(plot2); 
} 
void 
PlotOne(void) 
{?fprintf(plot1,?"%s",?startplot1); 
fflush(plot1); 
fprintf(plot2,?"%s",?startplot2); 
fflush(plot2); 
} 
void 
RePlot(void) 
{?fprintf(plot1,?"%s",?replot); 
fflush(plot1); 
} 
The?header?file?externals.h?contains?the?following:? 
/*?externals.h?*/ 
#ifndef?EXTERNALS 
#define?EXTERNALS 

#include? 
#include? 
#include? 

/*?prototypes?*/ 

void?StartPlot(void); 
void?RemoveDat(void); 
void?StopPlot(void); 
void?PlotOne(void); 
void?RePlot(void); 
#endif?

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -