Linux 进程间通信-管道课件

上传人:我*** 文档编号:145239195 上传时间:2020-09-18 格式:PPT 页数:37 大小:260KB
返回 下载 相关 举报
Linux 进程间通信-管道课件_第1页
第1页 / 共37页
Linux 进程间通信-管道课件_第2页
第2页 / 共37页
Linux 进程间通信-管道课件_第3页
第3页 / 共37页
Linux 进程间通信-管道课件_第4页
第4页 / 共37页
Linux 进程间通信-管道课件_第5页
第5页 / 共37页
点击查看更多>>
资源描述

《Linux 进程间通信-管道课件》由会员分享,可在线阅读,更多相关《Linux 进程间通信-管道课件(37页珍藏版)》请在金锄头文库上搜索。

1、第7章 进程间通信:管道,2,主要内容,管道的定义 popen和pclose库函数 pipe系统调用 父进程和子进程 命名管道:FIFO 客户/服务器架构,3,什么是管道,管道(pipe) Shell中的管道机制 e.g. cmd1 | cmd2 管道是半双工,而且一般是传送方向固定的单向管道 管道也是一种文件 管道不允许文件定位,读从文件的开始处读。 数据在管道中是以先进先出的方式传送,4,popen int pclose(FILE *stream_to_close);,5,int main() FILE *read_fp; char bufferBUFSIZ + 1; int chars_

2、read; memset(buffer, 0, sizeof(buffer); read_fp = popen(uname -a, r); if (read_fp != NULL) chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp); if (chars_read 0) printf(Output was:-n%sn, buffer); pclose(read_fp); exit(EXIT_SUCCESS); exit(EXIT_FAILURE); ,通过管道读取数据,6,将输出送往popen,int main() FILE *w

3、rite_fp; char bufferBUFSIZ + 1; sprintf(buffer, Once upon a time, there was.n); write_fp = popen(od -c, w); if (write_fp != NULL) fwrite(buffer, sizeof(char), strlen(buffer), write_fp); pclose(write_fp); exit(EXIT_SUCCESS); exit(EXIT_FAILURE); ,7,popen函数分析,一方面shell对所有命令参数进行扩展处理,用popen可以启动复杂的shell命令。

4、 另一方面,使用shell导致popen实际上派生了两个子进程,占用了较多的系统资源,8,pipe 系统调用,pipe 函数: 创建一个管道,提供对读写数据更多的控制。 #include int pipe(int filedes2); (Returned value: 0 if success, -1 if failure) pipe: FIFO,filedes用来保存标识管道的文件描述符,filedes0 用来从管道读出数据,filedes1用来向管道写入数据,9,单个进程的pipe,10,#include #include #define MSGSIZE 16 char *msg1=“he

5、llo,world #1”; char *msg2=“hello,world #2”; char *msg3=“hello,world #3”;,main() char inbufMSGSIZE; int p2,j; if(pipe(p)=-1) perror(“pipe call”); exit(1); ,11,write(p1,msg1,MSGSIZE); write(p1,msg2,MSGSIZE); write(p1,msg3,MSGSIZE); for(j=0;j3;j+) read(p0,inbuf,MSGSIZE); printf(“%sn”,inbuf); exit(0); ,

6、12,父子进程间管道通信,13,管道和exec函数,int main() int data_processed; int file_pipes2; const char some_data = 123; char bufferBUFSIZ + 1; pid_t fork_result; memset(buffer, 0, sizeof(buffer); if (pipe(file_pipes) = 0) fork_result = fork(); if (fork_result = (pid_t)-1) fprintf(stderr, Fork failure); exit(EXIT_FAIL

7、URE); if (fork_result = 0) sprintf(buffer, %d, file_pipes0); (void)execl(pipe4, pipe4, buffer, (char *)0); exit(EXIT_FAILURE); else data_processed = write(file_pipes1, some_data, strlen(some_data); printf(%d - wrote %d bytesn, getpid(), data_processed); exit(EXIT_SUCCESS); ,14,pipe4.c,int main(int a

8、rgc, char *argv) int data_processed; char bufferBUFSIZ + 1; int file_descriptor; memset(buffer, 0, sizeof(buffer); sscanf(argv1, %d, ,15,pipe read int dup2(int file_descriptor_one, file_descriptor_two),17,18,if (pipe(file_pipes) = 0) fork_result = fork(); if (fork_result = (pid_t)-1) fprintf(stderr,

9、 Fork failure); exit(EXIT_FAILURE); if (fork_result = (pid_t)0) close(0); dup(file_pipes0); close(file_pipes0); close(file_pipes1); execlp(od, od, -c, (char *)0); exit(EXIT_FAILURE); else close(file_pipes0); data_processed = write(file_pipes1, some_data, strlen(some_data);,管道和dup函数,19,FIFO: 命名管道,管道和

10、命名管道 相同点 进程间传送数据,也是半双工方式,数据处理基于FIFO 不同点 命名管道作为一种特殊文件纳入文件系统,和一般文件一样有名字,在文件系统的目录树中有命名管道的目录项,磁盘上有其对应的inode节点 管道一般只用于父子进程之间的通信,命名管道应用范围更广。 mkfifo(1), mkfifo(2), mknod(1), mknod(2),20,创建FIFO,mkfifo: 创建命名管道 #include #include int mkfifo(const char *filename, mode_t mode); (Returned value: 0 if success, -1

11、if failure),21,创建命名管道,int main() int res = mkfifo(/tmp/my_fifo, 0777); if (res = 0) printf(FIFO createdn); exit(EXIT_SUCCESS); ,22,用open打开一个FIFO,Review: “open” 系统调用 int open(const char *pathname, int flags); “flags” parameter 必须指定的互斥模式: O_RDONLY, O_WRONLY O_NONBLOCK consideration: 同步 读端/写端,23,FIFO的同

12、步,打开FIFO时的同步 一般情况下(没有说明O_NONBLOCK),只读打开要阻塞到某个其它进程为写打开此FIFO;类似的,为写打开一个FIFO要阻塞到某个其它进程为读而打开它。 如果指定了O_NONBLOCK,则只读打开立即返回;只写打开也立即返回,但如果没有进程已经为读而打开此FIFO,那么open将出错返回 -1,errno置为ENXIO。,24,同步示例,shell中使用fifo的例子 cat my_fifo fifo2.c,25, for(i = 1; i argc; i+) if (strncmp(*+argv, O_RDONLY, 8) = 0) open_mode |= O_

13、RDONLY; if (strncmp(*argv, O_WRONLY, 8) = 0) open_mode |= O_WRONLY; if (strncmp(*argv, O_NONBLOCK, 10) = 0) open_mode |= O_NONBLOCK; printf(Process %d opening FIFOn, getpid(); res = open(FIFO_NAME, open_mode); printf(Process %d result %dn, getpid(), res); sleep(5); ,fifo2.c,26,27,读写FIFO,读写操作的行为受FIFO

14、打开标志O_NONBLOCK 的影响: 1. 对一个空的、阻塞的read调用将阻塞,直至 有数据可以读时才继续执行,对一个空的、 非阻塞的FIFO的调用将立刻返回0字节。 2.对于设置了阻塞标志的写操作: 当要写入的数据量不大于PIPE_BUF时,linux将 保证写入的原子性。如果此时管道空闲缓冲区不足以容纳要写入的字节数,则进入睡眠,直到当缓冲区中能够容纳要写入的字节数时,才开始进行一次性写操作。,28,读写FIFO,当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。FIFO缓冲区一有空闲区域,写进程就会试图向管道写入数据,写操作在写完所有请求写的数据后返回。 对于

15、没有设置阻塞标志的写操作: 当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。在写满所有FIFO空闲缓冲区后,写操作返回。 当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。如果当前FIFO空闲缓冲区能够容纳请求写入的字节数,写完后成功返回;如果当前FIFO空闲缓冲区不能够容纳请求写入的字节数,则返回EAGAIN错误,提醒以后再写。,29,FIFO的应用(1),生产者消费者程序 例fifo.4,30,生产者程序, int open_mode = O_WRONLY; printf(Process %d opening FIFO O_WRONLYn, getpid(); pipe_fd = open(FIFO_NAME, open_mode); printf(Process %d result %dn, getpid(), pipe_fd); if (pipe_fd != -1) while(bytes_sent TEN_MEG) res = write(pipe_fd, buffer, BUFFER_SIZE); if (res = -1) fprintf(stderr, Write error on pipen); exit(

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 办公文档 > PPT模板库 > PPT素材/模板

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号