管道通信(上)
(一)概述
Linux Shell 都允许重定向,而重定向使用的就是管道。例如,ps | grep vsftpd 。管道是单向的、先进先出的、无结构的、固定大小的字节流。管道是Linux由Unix那里继承过来的进程间的通信机制,它是Unix早期的一个重要通信机制。其思想是,在内存中创建一个共享文件,从而使通信双方利用这个共享文件来传递信息。由于这种方式具有单向传递数据的特点,所以这个作为传递消息的共享文件就叫做“管道”。它把一个进程的标准输出和另一个进程的标准输入连接在一起。写进程在管道的尾端写入数据,读进程在管道的读端读出数据。数据读出之后将从管道中移走,其他读进程都不能再读到这些数据。管道提供了简单的流控制机制。进程试图读空管道时,在有数据写入管道之前,进程将一直阻塞。同样,管道已经满时,进程在试图写管道,在其他进程从管道中移走数据之前,写进程将一直阻塞。
(二)匿名管道
匿名管道是具有共同祖先的进程之间的一种通信方式,因此通常用于父子进程或者兄弟进程之间的通信,在由父进程创建的子进程将会赋值父进程包括文件在内的一些资源。如果父进程创建子进程之前创建了一个文件,那么这个文件的描述符就会被父进程在随后所创建的子进程所共享。也就是说,父、子进程可以通过这个文件进行通信。
参数:长度为2的整型数组
返回值:成功返回0,失败返回-1,errno会被设置,可以通过perror打印错误信息。
函数使用示例:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<unistd.h> 5 int main(int argc, char const *argv[]) 6 { 7 int fd_pipe[2]; 8 if(pipe(fd_pipe) == -1) 9 { 10 perror("pipe"); 11 exit(1); 12 } 13 if(write(fd_pipe[1],"hello pipe",strlen("hello pipe")) == -1) 14 { 15 perror("write"); 16 exit(1); 17 } 18 char buf[128] = ""; 19 if(read(fd_pipe[0],buf,sizeof(buf)) == -1) 20 { 21 perror("read"); 22 exit(1); 23 } 24 printf("%s ",buf); 25 close(fd_pipe[1]); 26 close(fd_pipe[0]); 27 return 0; 28 }
运行结果:
父子进程之间通信示例:父进程从终端读取内容,并将内容发送给子进程。
1 #include<unistd.h> 2 #include<stdio.h> 3 #include<string.h> 4 #include<stdlib.h> 5 int main(int argc, char const *argv[]) 6 { 7 int fd_pipe[2]; 8 pid_t pid; 9 if(pipe(fd_pipe) == -1) 10 { 11 perror("fail to pipe"); 12 exit(1); 13 } 14 if((pid = fork()) == -1) 15 { 16 perror("Fail to fork"); 17 exit(1); 18 } 19 else if (pid > 0) 20 { 21 char buf[20] = ""; 22 while (1) 23 { 24 if(read(STDIN_FILENO,buf,sizeof(buf)) == -1) 25 { 26 perror("Fail to read from std"); 27 exit(1); 28 } 29 buf[strlen(buf) - 1] = '