linux中管道(pipe)一谈
来源:互联网 发布:战国史se人物数据 编辑:程序博客网 时间:2024/06/02 06:47
/*********************************************** 管道(pipe)是Linux上进程间通信的一种方式,其是半双工(数据流只能在一个方向上流动(还需要经过内核),及要么是接收,要么是发送),并且只能在父子进程 或 具有公共祖先的两个子进程间通信。 管道(pipe)一般是在调用fork函数之前调用pipe函数创建,这样的话,fork后子进程将得到父进程的两个管道描述符副本(相当于调用了两次dup)。/***********************************************相关函数: #include <unistd.h> int pipe(int fd[2]) 返回值:成功返回0,失败返回-1***********************************************/注意: 函数执行成功后为参数返回两个描述符,fd[0]为读而打 开,fd[1]为写而打开很多系统在stat结构体st_size成员中储存管道中可用于读写字节数。但这是不可移植的。(对于struct stat不了解的请百度)使用管道有几点注意事项:1.当读(read)一个写(write)端已经关闭的管道,程序(read)将读完管道中所有数据后返回0。2.当写(write)一个读(write)端已经关闭的管道,将产SIGPIP信号,程序(write)返回-1,并将错误码置为EPIPE3.如果管道中数据为空,则(read)将永久堵塞直到有数据或写(write)端关闭。4.如果管道已被数据填满,则(write)将会堵塞直到管道中有空与空间 或 写端(read)关闭,(管道容量可用fpathconf函数得到,使用_PC_PIPE_BUF参数)。***********************************************/
实例1: 使用管道实现 ls -l | wc -c 操作分析: 执行ls -l后其结果将会被打印到终端(即使用到STDOUT_FILENO)标准输出,wc -c(统计单词数量)是从标准输入中得到内容(即使用到STDIN_FILENO)然后进行统计。思路: 子进程中调用exec函数族执行ls -l命令,并调用dup2函数将子进程中的fd[1]描述符复制为标准输出(STDOUT_FILENO),这用的话,但向标准输出中写数据是就等同于向管道中写数据。 对于父进程则调用exec函数族执行wc -c命令,然后调用dup2将fd[0]复制为标准输入,实例代码:#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>int main(int argc, char **argv){ pid_t pid; int fd[2]; /**创建管道**/ if (pipe(fd) < 0) { perror("pipe error"); return EXIT_FAILURE; } /**调用fork函数创建子进程**/ if ((pid = fork()) < 0) { perror("fork error"); return EXIT_FAILURE; } else if (0 == pid) { close(fd[0]); /**关闭不必要的描述符**/ if (fd[1] != STDOUT_FILENO) { if (dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO) { perror("dup2 error to stdout"); return EXIT_FAILURE; } close(fd[1]); } execlp("ls", "ls", "-l", NULL); exit(EXIT_SUCCESS); } //sleep(2); close(fd[1]); if (fd[0] != STDIN_FILENO) { if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO) { perror("dup2 error to stdin"); return EXIT_FAILURE; } close(fd[0]); } execlp("wc", "wc", "-c", NULL); /**回收子进程的退出状态,避免产生僵死进程**/ if (waitpid(pid, NULL, 0) < 0) { perror("waitpid error"); return EXIT_FAILURE; } return EXIT_SUCCESS;}
实例2: 实现分页功能 即more命令#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#define PAGE "/bin/more"#define MAXLINE 1024int main(int argc, char **argv){ pid_t pid; int fd[2]; char line[MAXLINE]; char *page = NULL, *temp = NULL, *arg = NULL; FILE *fp = NULL; if (argc != 2) { printf("Usage: %s <filename>\n", argv[0]); return EXIT_FAILURE; } if ((fp = fopen(argv[1], "r")) == NULL) { perror("fopen error"); return EXIT_FAILURE; } if (pipe(fd) < 0) { perror("pipe error"); return EXIT_FAILURE; } if ((pid = fork()) < 0) { perror("fork error"); return EXIT_FAILURE; } else if (0 == pid) { close(fd[0]); int len; while (fgets(line, MAXLINE, fp) != NULL) { len = strlen(line); int offset = 0, n = 0; while (len) { n = write(fd[1], line+offset, len); offset += n; len -= n; } } if (ferror(fp)) { perror("fgets errro"); return EXIT_FAILURE; } fclose(fp); close(fd[1]); } close(fd[1]); if (fd[0] != STDIN_FILENO) { if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO) { perror("dup2 error to stdin"); return EXIT_FAILURE; } close(fd[0]); } /***得到PAGE对应的环境参数***/ if ((page = getenv("PAGE")) != NULL) { arg = page; } else { arg = PAGE; } /** *strrchr函数判断'\'字符, *在arg字符串中最后一次出现的位置 **/ if ((temp = strrchr(arg, '/')) != NULL) { temp++; } else { temp = arg; } execl(arg, temp, NULL); if (waitpid(pid, NULL, 0) < 0) { perror("waitpid error"); return EXIT_FAILURE; } return EXIT_SUCCESS;}
阅读全文
2 0
- linux中管道(pipe)一谈
- linux系统编程之管道(一):匿名管道(pipe)
- linux系统编程之管道(一):匿名管道(pipe)
- linux--管道pipe
- Linux 管道(pipe)
- Linux pipe(管道)
- linux管道pipe
- linux管道(pipe)
- linux管道pipe详解
- 【linux】匿名管道pipe
- Linux 管道pipe
- linux管道pipe详解
- linux pipe 无名管道
- linux管道pipe详解
- Linux进程通信(一)——pipe管道
- Linux--进程间通信(一)-管道(pipe)通信
- Linux进程间通讯一--无名管道PIPE
- linux 管道(linux Pipe与named Pipe)
- Linux下/usr/local/lib 和 /usr/lib 里的内容有什么区别?
- linux(二)------多线程并发服务器
- OpenCL优化方法-Single Work-Item Kernel的良好设计实践
- Menu初级入门
- Kmeans聚类代码实现、作业及优化
- linux中管道(pipe)一谈
- MyEclipse 优化配置以及Building Workspace时间太长的问题解决
- 数据库事务
- STM32的USART发送数据时如何使用TXE和TC标志(认识1)
- scrapy中的item_loader
- Python--get和post请求
- 创建JPA工程时提示:at least one user library must be selected
- hdu 1159 Common Subsequence
- POJ 1006 生理周期