一、 父子进程通信 lswc-l
父进程ls写到管道,子进程wc管道的内容
父进程创建管道(拥有读写两端),父进程fork子进程,父进程要将原本输出到屏幕上的内容输出到管道中,用dup实现,然后execlp去进行ls操作;子进程同理,将原本从标准输入的内容变从管道去读取,用dup实现,再用execlp去进行wc操作
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<unistd.h>
#include<pthread.h>
void sys_err(const char *str)
{
perror(str);
exit(1);
}
int main(int argc, char* argv[])
{
int fd[2];
int ret;
pid_t pid;
ret = pipe(fd);//父进程与管道的读端写端都在位
if(ret == -1)
sys_err("pipe error");
pid = fork();
if(pid == -1)
{
sys_err("fork error");
}else if(pid>0)//父进程
{
close(fd[0]);//关闭读端
dup2(fd[1],STDOUT_FILENO);//ls的输出进管道
execlp("ls","ls",NULL);
//close回收是没有用的,因为execlp一运行除非报错不然不回来
sys_err("execlp err");
}else if(pid == 0)
{
close(fd[1]);
dup2(fd[0],STDIN_FILENO);//原来从标准输入读,现在从管道读
execlp("wc","wc","l",NULL);
}//这样的执行结果输出是到屏幕的
//dup(1,2),2指向1,所以应该是标准输出b
return 0;
}
二、兄弟进程通信
兄:ls ;弟:wc-l ;父:等待回收子进程
要求:使用“循环创建N个子进程”创建兄弟进程,使用循环因子i标示,注意管道读写行为
注意,要把父进程的读写端撤掉,不然管道数据无法单向流通:
代码👇
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<unistd.h>
#include<pthread.h>
#include<sys/wait.h>
void sys_err(const char *str)
{
perror(str);
exit(1);
}
int main(int argc, char* argv[])
{
int fd[2];
int ret,i;
pid_t pid;
ret = pipe(fd);//父进程与管道的读端写端都在位
if(ret == -1)
sys_err("pipe error");
for(i =0; i<2; ++i)//循环创建N个子进程
{
pid = fork();
if(pid == -1)
{
sys_err("fork error");
}
if(pid == 0)
break;
}//0 1 是两个子进程,2是父进程
if(i == 2)//父进程 回收
{
close(fd[0]);
close(fd[1]);
wait(NULL);
wait(NULL);
}else if(i == 0)//兄 写到管道中,关闭,dup2,execlp
{
close(fd[0]);
dup2(fd[1],STDOUT_FILENO);
execlp("ls","ls",NULL);
sys_err("execlp ls error");
} else if(i == 1)//弟
{
close(fd[1]);//关写
dup2(fd[0],STDIN_FILENO);
execlp("wc","wc","-l",NULL);
sys_err("execlp wc error");
}
}
另外问题:是否允许一个pipe有一个写端,多个读端?是否允许一个读端多个写端?
一个写端多个读端,是允许的(用sleep控制顺序),但是平常不怎么用
三、多个读写端操作管道及管道缓冲区大小
四、命名管道fifo的创建和原理
pipe之所以能进行通信是因为父进程通过fork将对管道的读写复制给了子进程,如果不是有血缘关系的进程的话就无法通过pipe通信,但是进程使用的是同一块内核空间,因此可以通过再内核中创建一块缓冲区以进行通信,这就是fifo的实现原理
语法示例👇
五、fifo实现非血缘间进程通信
创建fifo之后就是文件读写操作