当前位置:Linux教程 - Linux综合 - IPC和管道简介

IPC和管道简介

作者: 黄浩文 1 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 */
[1] [2] [3] 下一页 

/* 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";
上一页 [1] [2] [3] 下一页 

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 作者的电子邮件地址是:[email protected]

(出处:http://www.sheup.com)


上一页 [1] [2] [3] 

#endif 作者的电子邮件地址是:[email protected]

(出处:http://www.sheup.com)


上一页 [1] [2] [3] [4]