网络应用程序设计(方敏)-第5章 进程间通信及实现方法
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
(1) 管道是一个单向的通信信道,发送进程能以比 较简单的方式,把要发送的信息以信息流的方式写入信 道,不需要考虑对每次传送信息长度的限制。
第5章 进程间通信及实现方法
(2) 接收进程从信道按需取用信息,不必考虑长度 限制。
(3) 发送和接收进程的实施相互协调,其中发送和 接收进程相互协调指的是:
第5章 进程间通信及实现方法
while (wait()!=pid); /* 等待原子进程运行返回 */ close(chpipe1[1]); close(chpipe2[0]);
} else { /* 在子进程中 */
close(chpipe1[1]); close(chpipe2[0]);
第5章 进程间通信及实现方法 pro_server(chpipe1[0],chpipe2[1]); close(chpipe1[0]); close(chpipe2[1]); } exit(0); } 其中顾客子程序为: #include <stdlio.h> pro_client(rfd, wfd) int rfd; int wfd;
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)
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");
第5章 进程间通信及实现方法
if
(write(chpipe1[1] , parstr ,
sizeof(parstr))!=sizeof(parstr))
err_sys ("send error");
close (chpipe1[1]);
if (read(chpipe2[0],buff,100)<=0)
下面的例子说明了管道机构的建立和使用。
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章 进程间通信及实现方法
1.通过命名管道发信息 #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #include <fcntl.h> #define FIFO_SERVER "/tmp/fifos_server"
第5章 进程间通信及实现方法 main(int argc,char** argv) /* 参数为即将写入的字节数 */ { int fd,n; char w_buf[512]; int write_num; n=100; memset(w_buf,0,512); strncpy(w_buf,argv[1],n);
如果将上面程序改为在顾客—服务员模式上运行,上 例程序可改写为:由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");
Hale Waihona Puke Baidu 第5章 进程间通信及实现方法
5.2 命名管道
命名管道与管道不同之处在于,它与一个路径名关 联,以FIFO的文件形式存在于文件系统中。这样,即使 与FIFO的创建进程无亲缘关系的进程,只要可以访问该 路径,就能够彼此通过FIFO相互通信。
系统调用mkfifo() 创建命名管道: int mkfifo(const char * pathname , mode_t mode);
close (chpipe2[1]);
}
第5章 进程间通信及实现方法
运行结果 child process: the datas from parent. parent process: the datas from child. 程序中信息的传输过程如图5-2所示。
第5章 进程间通信及实现方法
chpipe1
err_sys("server:file read has error"); buff[n]='\0'; if ((fd=open(buff,0))<0) { strcpy(errbuf,"file can't open.\n"); strcat(buff,errbuff); n=strlen(buff); if(write(wfd,buff,n)!=n) err_sys("server:message send error")
① 发送和接收进程对通信信道的使用是互斥的,一 个进程利用信道进行读或写操作时,其他进程就不能用, 当这个进程不用信道时,其他的进程才能使用。
② 发送和接收进程都能了解对方是否存在。 ③ 发送和接收进程同步。即接收进程在信道中已有 信息时,才接收信息;发送进程要在信道空闲时,才能 发送信息。
第5章 进程间通信及实现方法 管道是由系统调用pipe建立的,其调用格式为: #include <unistd.h> int pipe(int fd[2]); 参数fd指向两个文件描述符;fd[0]返回管道
}
第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)
当需要进行双向数据传输时,必须建立两 个管道。每个管道负责一个方向的数据传输。它的操作过 程如下:
● 创建两个管道:管道1和管道2; ● 调用fork()产生子进程; ● 父进程关闭管道1的读端;
第5章 进程间通信及实现方法
● 父进程关闭管道2的写端;
● 子进程关闭管道1的写端;
● 子进程关闭管道2的读端。
第5章 进程间通信及实现方法
if ((mkfifo(FIFO_SERVER, O_CREAT|O_EXCL)<0)&&(errno!=EEXIST))
printf("can’t create fifos_server\n"); /* 设置非阻塞标志 */ fd=open(FIFO_SERVER, O_WRONLY|O_NONBLOCK,0); write_num = write(fd,w_buf,n);
父进程
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],两者进行通信。就 每个管道而言,均是单向管道,其数据信息只按一个方向 流动。就每个进程而言,信息的传送是双向的,即能发送 又能接收。
读通道打开的文件号,用于读;fd[1]返回管道的写通道 打开的文件号,用于写,如图5-1所示。
第5章 进程间通信及实现方法
write
fd[1]
管道
fd[0]
read
图5-1 管道工作示意图
第5章 进程间通信及实现方法
2.管道的共享使用 进程利用pipe系统调用生成管道后,通常接着就要创 建一个或几个子进程,管道被父子进程共享。每个进程可 以用类似文件读写操作方式对管道进行存取操作。一般情 况下,一个管道最好为两个进程专用,一个进程只用其发 送端,另一个进程只用其接收端。
}
第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");
}
}
第5章 进程间通信及实现方法
程序pro_client中的父进程通过管道发送文件名给 子进程,pro_server中的子进程通过管道读文件名,如 果接收的文件名有错,文件打不开,则将错误信息回传 给client方(父进程);否则,读文件中的信息并将文件 信息回传给client。
利用管道的只能在父子进程间的通信,对于两个完 全不相关的进程不能采用管道进行通信,这是管道的一 个特点。
第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);
第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章 进程间通信及实现方法
该函数的pathname是一个路径名,也就是创建后命 名管道的名字,mode打开文件的模式,与打开普通文件 的open()函数中文件操作模式参数相似。如果mkfifo的 第一个参数是一个已经存在的路径名时,则返回类型为 EEXIST 的 错 误 ; 如 果 返 回 该 错 误 , 那 么 只 要 调 用 打 开 FIFO的函数就可以了。生成了命名管道后,就可以使用 一般的文件I/O函数如open、close、read、write等来对 它进行操作。
第5章 进程间通信及实现方法
第5章 进程间通信及实现方法
5.1 管道 5.2 命名管道 5.3 消息通信 5.4 共享内存 5.5 信号灯 5.6 UNIX域套接字 习题
第5章 进程间通信及实现方法
5.1 管道
1. 管道的定义 Linux系统提供了几种通信方式,如消息队
列、信号量及共享内存等。它们有的需要使用较多的存 储资源才能进行信息传递,有的不适合在进程间进行大 量的信息传递。而管道机构能够为进程之间大量信息的 传输提供通道。管道是Linux系统利用文件系统为基础构 成的一种进程间通信的机构。它有以下几个特点:
第5章 进程间通信及实现方法
(2) 接收进程从信道按需取用信息,不必考虑长度 限制。
(3) 发送和接收进程的实施相互协调,其中发送和 接收进程相互协调指的是:
第5章 进程间通信及实现方法
while (wait()!=pid); /* 等待原子进程运行返回 */ close(chpipe1[1]); close(chpipe2[0]);
} else { /* 在子进程中 */
close(chpipe1[1]); close(chpipe2[0]);
第5章 进程间通信及实现方法 pro_server(chpipe1[0],chpipe2[1]); close(chpipe1[0]); close(chpipe2[1]); } exit(0); } 其中顾客子程序为: #include <stdlio.h> pro_client(rfd, wfd) int rfd; int wfd;
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)
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");
第5章 进程间通信及实现方法
if
(write(chpipe1[1] , parstr ,
sizeof(parstr))!=sizeof(parstr))
err_sys ("send error");
close (chpipe1[1]);
if (read(chpipe2[0],buff,100)<=0)
下面的例子说明了管道机构的建立和使用。
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章 进程间通信及实现方法
1.通过命名管道发信息 #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #include <fcntl.h> #define FIFO_SERVER "/tmp/fifos_server"
第5章 进程间通信及实现方法 main(int argc,char** argv) /* 参数为即将写入的字节数 */ { int fd,n; char w_buf[512]; int write_num; n=100; memset(w_buf,0,512); strncpy(w_buf,argv[1],n);
如果将上面程序改为在顾客—服务员模式上运行,上 例程序可改写为:由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");
Hale Waihona Puke Baidu 第5章 进程间通信及实现方法
5.2 命名管道
命名管道与管道不同之处在于,它与一个路径名关 联,以FIFO的文件形式存在于文件系统中。这样,即使 与FIFO的创建进程无亲缘关系的进程,只要可以访问该 路径,就能够彼此通过FIFO相互通信。
系统调用mkfifo() 创建命名管道: int mkfifo(const char * pathname , mode_t mode);
close (chpipe2[1]);
}
第5章 进程间通信及实现方法
运行结果 child process: the datas from parent. parent process: the datas from child. 程序中信息的传输过程如图5-2所示。
第5章 进程间通信及实现方法
chpipe1
err_sys("server:file read has error"); buff[n]='\0'; if ((fd=open(buff,0))<0) { strcpy(errbuf,"file can't open.\n"); strcat(buff,errbuff); n=strlen(buff); if(write(wfd,buff,n)!=n) err_sys("server:message send error")
① 发送和接收进程对通信信道的使用是互斥的,一 个进程利用信道进行读或写操作时,其他进程就不能用, 当这个进程不用信道时,其他的进程才能使用。
② 发送和接收进程都能了解对方是否存在。 ③ 发送和接收进程同步。即接收进程在信道中已有 信息时,才接收信息;发送进程要在信道空闲时,才能 发送信息。
第5章 进程间通信及实现方法 管道是由系统调用pipe建立的,其调用格式为: #include <unistd.h> int pipe(int fd[2]); 参数fd指向两个文件描述符;fd[0]返回管道
}
第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)
当需要进行双向数据传输时,必须建立两 个管道。每个管道负责一个方向的数据传输。它的操作过 程如下:
● 创建两个管道:管道1和管道2; ● 调用fork()产生子进程; ● 父进程关闭管道1的读端;
第5章 进程间通信及实现方法
● 父进程关闭管道2的写端;
● 子进程关闭管道1的写端;
● 子进程关闭管道2的读端。
第5章 进程间通信及实现方法
if ((mkfifo(FIFO_SERVER, O_CREAT|O_EXCL)<0)&&(errno!=EEXIST))
printf("can’t create fifos_server\n"); /* 设置非阻塞标志 */ fd=open(FIFO_SERVER, O_WRONLY|O_NONBLOCK,0); write_num = write(fd,w_buf,n);
父进程
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],两者进行通信。就 每个管道而言,均是单向管道,其数据信息只按一个方向 流动。就每个进程而言,信息的传送是双向的,即能发送 又能接收。
读通道打开的文件号,用于读;fd[1]返回管道的写通道 打开的文件号,用于写,如图5-1所示。
第5章 进程间通信及实现方法
write
fd[1]
管道
fd[0]
read
图5-1 管道工作示意图
第5章 进程间通信及实现方法
2.管道的共享使用 进程利用pipe系统调用生成管道后,通常接着就要创 建一个或几个子进程,管道被父子进程共享。每个进程可 以用类似文件读写操作方式对管道进行存取操作。一般情 况下,一个管道最好为两个进程专用,一个进程只用其发 送端,另一个进程只用其接收端。
}
第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");
}
}
第5章 进程间通信及实现方法
程序pro_client中的父进程通过管道发送文件名给 子进程,pro_server中的子进程通过管道读文件名,如 果接收的文件名有错,文件打不开,则将错误信息回传 给client方(父进程);否则,读文件中的信息并将文件 信息回传给client。
利用管道的只能在父子进程间的通信,对于两个完 全不相关的进程不能采用管道进行通信,这是管道的一 个特点。
第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);
第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章 进程间通信及实现方法
该函数的pathname是一个路径名,也就是创建后命 名管道的名字,mode打开文件的模式,与打开普通文件 的open()函数中文件操作模式参数相似。如果mkfifo的 第一个参数是一个已经存在的路径名时,则返回类型为 EEXIST 的 错 误 ; 如 果 返 回 该 错 误 , 那 么 只 要 调 用 打 开 FIFO的函数就可以了。生成了命名管道后,就可以使用 一般的文件I/O函数如open、close、read、write等来对 它进行操作。
第5章 进程间通信及实现方法
第5章 进程间通信及实现方法
5.1 管道 5.2 命名管道 5.3 消息通信 5.4 共享内存 5.5 信号灯 5.6 UNIX域套接字 习题
第5章 进程间通信及实现方法
5.1 管道
1. 管道的定义 Linux系统提供了几种通信方式,如消息队
列、信号量及共享内存等。它们有的需要使用较多的存 储资源才能进行信息传递,有的不适合在进程间进行大 量的信息传递。而管道机构能够为进程之间大量信息的 传输提供通道。管道是Linux系统利用文件系统为基础构 成的一种进程间通信的机构。它有以下几个特点: