?? pipes.html.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 + -