当前位置:文档之家› 网络应用程序设计(方敏)-第5章 进程间通信及实现方法

网络应用程序设计(方敏)-第5章 进程间通信及实现方法

பைடு நூலகம்
第5章 进程间通信及实现方法
{ char parstr[]={"parfile.dat"}; int n; char buff[100]; n=strlen(parstr); if (write(wfd,parstr,n)!=n) err_sys("client: send error"); if (read(rfd,buff,100)<=0) err_sys("client: receive error"); else printf("parent process:%s\n",buff);
err_sys("receive error");
else
printf("parent process:%s\n",buff);
} /* fork */
第5章 进程间通信及实现方法
else { close(chpipe1[1]); 中 */
/* 在子进程
close(chpipe2[0]);
if (read(chpipe1[0],buff,100)<=0)
}
}
第5章 进程间通信及实现方法
程序pro_client中的父进程通过管道发送文件名给 子进程,pro_server中的子进程通过管道读文件名,如 果接收的文件名有错,文件打不开,则将错误信息回传 给client方(父进程);否则,读文件中的信息并将文件 信息回传给client。
利用管道的只能在父子进程间的通信,对于两个完 全不相关的进程不能采用管道进行通信,这是管道的一 个特点。
if (pipe(chpipe1)<0) err_sys("pipe1 creat error");
if (pipe(chpipe2)<0) err_sys("pipe2 creat error");
if (fork()) { /*在父进程中 */ close(chpipe1[0]); close(chpipe2[1]);
err_sys("receive error");
else
buff);
printf("child process : %s\n" ,
if (write(chpipe2[1] , chistr , sizeof(chistr))!=sizeof(chistr))
err_sys("send error");
当需要进行双向数据传输时,必须建立两 个管道。每个管道负责一个方向的数据传输。它的操作过 程如下:
● 创建两个管道:管道1和管道2; ● 调用fork()产生子进程; ● 父进程关闭管道1的读端;
第5章 进程间通信及实现方法
● 父进程关闭管道2的写端;
● 子进程关闭管道1的写端;
● 子进程关闭管道2的读端。
父进程
chpipe1[1]
chpipe2
chpipe1[0]
chpipe2[0]
chpipe2[1]
子进程
图5-2 利用管道进行通信
第5章 进程间通信及实现方法
首先,进程创建两个管道chpipe1和chpipe2,然后利 用 fork 产生一子进程。如果子进程创建成功,父进程利 用管道chpipe1[1]作写入端,用管道chpipe2[0]作读出端, 关 闭 管 道 端 chpipe1[0] 和 chpipe2[1] 。 子 进 程 用 管 道 chpipe1[0]作为读出端,用管道chpipe2[1]作为写入端, 关闭管道端chpipe1[1]和chpipe2[0],两者进行通信。就 每个管道而言,均是单向管道,其数据信息只按一个方向 流动。就每个进程而言,信息的传送是双向的,即能发送 又能接收。
① 发送和接收进程对通信信道的使用是互斥的,一 个进程利用信道进行读或写操作时,其他进程就不能用, 当这个进程不用信道时,其他的进程才能使用。
② 发送和接收进程都能了解对方是否存在。 ③ 发送和接收进程同步。即接收进程在信道中已有 信息时,才接收信息;发送进程要在信道空闲时,才能 发送信息。
第5章 进程间通信及实现方法 管道是由系统调用pipe建立的,其调用格式为: #include <unistd.h> int pipe(int fd[2]); 参数fd指向两个文件描述符;fd[0]返回管道
}
第5章 进程间通信及实现方法
else { while ((n=read(fd,buff,1024))>0)
if(wirte(wfd,buff,n)!=n)
error");
err_sys("server : message send
if (n<0)
err_sys("server:read error");
读通道打开的文件号,用于读;fd[1]返回管道的写通道 打开的文件号,用于写,如图5-1所示。
第5章 进程间通信及实现方法
write
fd[1]
管道
fd[0]
read
图5-1 管道工作示意图
第5章 进程间通信及实现方法
2.管道的共享使用 进程利用pipe系统调用生成管道后,通常接着就要创 建一个或几个子进程,管道被父子进程共享。每个进程可 以用类似文件读写操作方式对管道进行存取操作。一般情 况下,一个管道最好为两个进程专用,一个进程只用其发 送端,另一个进程只用其接收端。
第5章 进程间通信及实现方法
5.2 命名管道
命名管道与管道不同之处在于,它与一个路径名关 联,以FIFO的文件形式存在于文件系统中。这样,即使 与FIFO的创建进程无亲缘关系的进程,只要可以访问该 路径,就能够彼此通过FIFO相互通信。
系统调用mkfifo() 创建命名管道: int mkfifo(const char * pathname , mode_t mode);
下面的例子说明了管道机构的建立和使用。
main()
{
char parent.\n"};
parstr[]={"the
datas
char child.\n"};
chistr[]={"the
datas
int chpipe1[2], chpipe2[2];
char buff[100];
from from
第5章 进程间通信及实现方法
第5章 进程间通信及实现方法 if ((pid=fork())<0) { err_sys("can't fork");} else if (pid) { /* 在父进程中 */ close(chpipe1[0]); close(chpipe2[1]); pro_client(chpipe2[0],chpipe1[1]);
第5章 进程间通信及实现方法
第5章 进程间通信及实现方法
5.1 管道 5.2 命名管道 5.3 消息通信 5.4 共享内存 5.5 信号灯 5.6 UNIX域套接字 习题
第5章 进程间通信及实现方法
5.1 管道
1. 管道的定义 Linux系统提供了几种通信方式,如消息队
列、信号量及共享内存等。它们有的需要使用较多的存 储资源才能进行信息传递,有的不适合在进程间进行大 量的信息传递。而管道机构能够为进程之间大量信息的 传输提供通道。管道是Linux系统利用文件系统为基础构 成的一种进程间通信的机构。它有以下几个特点:
如果将上面程序改为在顾客—服务员模式上运行,上 例程序可改写为:由main()产生一管道,然后产生一个子 进程。原进程运行顾客程序,而子进程运行服务员程序。
第5章 进程间通信及实现方法 main() { int chpipe1[2], chpipe2[2]; int pid; if (pipe(chpipe1)<0) err_sys("pipe1 creat error"); if (pipe(chpipe2)<0) err_sys("pipe2 creat error");
}
第5章 进程间通信及实现方法 服务员子程序为: #include <stdlio.h> pro_server(rfd, wfd) int rfd; int wfd; { int n; char buff[1024], errbuff[64]; int n, fd;
第5章 进程间通信及实现方法
/* 从 IPC 描述符中读文件名 */ if ((n=read(rfd,buff,1024))<=0)
第5章 进程间通信及实现方法
if
(write(chpipe1[1] , parstr ,
sizeof(parstr))!=sizeof(parstr))
err_sys ("send error");
close (chpipe1[1]);
if (read(chpipe2[0],buff,100)<=0)
close (chpipe2[1]);
}
第5章 进程间通信及实现方法
运行结果 child process: the datas from parent. parent process: the datas from child. 程序中信息的传输过程如图5-2所示。
第5章 进程间通信及实现方法
chpipe1
第5章 进程间通信及实现方法
该函数的pathname是一个路径名,也就是创建后命 名管道的名字,mode打开文件的模式,与打开普通文件 的open()函数中文件操作模式参数相似。如果mkfifo的 第一个参数是一个已经存在的路径名时,则返回类型为 EEXIST 的 错 误 ; 如 果 返 回 该 错 误 , 那 么 只 要 调 用 打 开 FIFO的函数就可以了。生成了命名管道后,就可以使用 一般的文件I/O函数如open、close、read、write等来对 它进行操作。
相关主题