进程间通信-pipe
进程间通信
每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信(IPC,InterProcess Communication)。
pipe
管道(pipe)就是一项基本的进程间通信的方法。
#include <unistd.h>
int pipe(int pipefd[2]);
使用pipe函数,就可以构建一条通信管道。
pipefd是传出参数,表示文件描述符。pipefd[0]是管道的读端,pipefd[1]是管道的写端。
成功,返回0;出错,返回-1。
管道的本质是环形队列。
管道的通用使用模式是先pipe。再fork。于是,父子进程都各有了一份管道的读端和写端。这表明父子进程本质上都可以读写管道,但使用中遵循只读只写的习惯:父子进程要么只读,要么只写。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
void sys_err(char *s)
{
perror(s);
exit(1);
}
int main(void)
{
char buf[100];
int fd[2];
pid_t pid;
if (pipe(fd) < 0) sys_err("pipe");
//get the size of pipe
printf("pipe size is %ld\n", fpathconf(fd[0], _PC_PIPE_BUF));
pid = fork();
if (pid < 0) sys_err("fork");
else if (0 == pid)
{
/* in child */
close(fd[1]); //子进程关闭写端
int n;
while (1)
{
n = read(fd[0], buf, 100);
write(STDOUT_FILENO, buf, n);
}
close(fd[0]);
}
else
{
/* in parent */
close(fd[0]); //父进程关闭读端
int i = 0;
while (1)
{
sprintf(buf, "zhangxiang %d\n", i++);
write(fd[1], buf, strlen(buf));
sleep(1);
}
close(fd[1]);
}
return 0;
}
pipe size is 4096
zhangxiang 0
zhangxiang 1
zhangxiang 2
zhangxiang 3
zhangxiang 4
zhangxiang 5
^c
以上的示例中父进程关闭读端,不断地往管道中写数据,子进程关闭写端,不断地从管道中读数据。这是典型的父子进程通过管道通信的方式。
父进程若是想读,子进程若是想写,则需另开辟一条管道进行通信。