歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux資訊 >> 更多Linux

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 */


/* 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 作者的電子郵件地址是:[email protected]



#endif 作者的電子郵件地址是:[email protected]



Copyright © Linux教程網 All Rights Reserved