目录
一、Linux进程间通信概述
1.UNIX平台进程通信方式
2.常用的进程间通信方式
二、无名管道PIPE
1.无名管道的特点:
2.无名管道的创建与关闭
创建无名管道
无名管道的读写
无名管道的读写特性
管道破裂例子
无名管道的大小
三、有名管道FIFO
1.有名管道的创建
2.有名管道进行通信例子
信进程主要局限在单个计算机内
首先来看创建函数
eg:
int main()
{
int pfd[2];
if (pipe(pfd) < 0) /*创建无名管道*/
{
printf("pipe create error\n");//利用返回值判断是否创建成功
return -1;
}
else
{
printf("pipe create success\n");
}
close(pfd[0]); /*关闭管道描述符*/
close(pfd[1]);
}
先举个例子实现子进程写入父进程读出
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
int pfd[2] = {0};//创建无名管道
int ret = pipe(pfd);
if(ret < 0)
{
perror("pipe");
exit(-1);
}
pid_t pid = fork();//创建子进程
if(pid < 0)
{
perror("fork");
exit(-1);
}
if(pid == 0)
{
char buf[64] = {0};//自定义缓冲区,用于存入终端输入信息
while(1)
{
fgets(buf, 64, stdin);
buf[strlen(buf)-1] = '\0';
write(pfd[1], buf, strlen(buf));//子进程执行写操作
}
}
else
{
char buf1[64] = {0};
while(1)//父进程进行读操作
{
memset(buf1, 0, 64);//清空缓冲区操作,因为自定义缓冲区可能存在上次读入的数据
read(pfd[0], buf1, 64);
printf("father ---- %s\n", buf1);//展示读入的数据
}
wait(NULL);//回收子进程资源
exit(0);
}
return 0;
}
读特性:
当写端存在时:
管道有数据:返回读到的字节数
管道无数据:阻塞
当写端不存在时:
管道有数据:返回读到的数据
管道无数据:返回0;
写特性:
当读端存在时:
管道有空间:返回写入的字节数
管道无空间:阻塞,直到有空间为止
当读端不存在时:
无论管道是否有空间,管道破裂 SIGPIPE
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
int pfd[2] = {0};
int ret = pipe(pfd); //创建无名管道
if(ret < 0)
{
perror("pipe");
exit(-1);
}
close(pfd[0]); //关闭无名管道的读端
pid_t pid = fork(); //创建子进程
if(pid == 0)
{
write(pfd[1], "hello", 5);
sleep(5);
}
else
{
int status;
wait(&status);
printf("%d %d %d\n", WIFEXITED(status),WIFSIGNALED(status),WTERMSIG(status));//展示错误信息
exit(0);
}
return 0;
}
可以以下方式计算
#include
#include
int main(int argc, char *argv[])
{
int pfd[2] = {0};
pipe(pfd);
int ret = 0;
int size = 0;
char buf[1] = {0};
while(1)//一直往管道里写数据
{
ret = write(pfd[1], buf, 1);//利用write返回值来计算,write会返回写入的字节数,这里我们一次就写一个0,然后循环进行累加,直到管道被塞满
size = size+ret;
printf("size = %d\n", size);
}
return 0;
}
这里注意几个要点
因为有名管道是一个文件,所以在操作有名文件时,要先创建一个有名文件,且操作时也有open和close操作
创建例子
#include
#include
#include
#include
int main(int argc, char *argv[])
{
int ret = mkfifo("fifo", 0664);//文件属性一般为0664
if(ret < 0)
{
perror("mkfifo");
exit(-1);
}
return 0;
}
读操作进程
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
int fd = open("fifo", O_RDONLY);
if(fd < 0)
{
perror("open");
exit(-1);
}
printf("open fifo ok!\n");
char buf[64] = {0};
while(1)
{
memset(buf, 0, 64);
read(fd, buf, 64);
printf("%s\n", buf);
}
close(fd);
return 0;
}
写操作进程
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
int fd = open("fifo", O_WRONLY);
if(fd < 0)
{
perror("open");
exit(-1);
}
printf("open fifo ok!\n");
char buf[64] = {0};
while(1)
{
fgets(buf, 64, stdin);
buf[strlen(buf)-1] = '\0';
write(fd, buf, strlen(buf));
}
close(fd);
return 0;
}
注:两个进程要同在运行状态,管道的读写操作才能执行,如果只有一方运行,程序会一直程阻塞状态