我们都知道,进程运行时是具有独立性的,要让两个进程进行通信是一件很困难的事情。因此两个进程通信的前提条件是,需要让两个进程看到同一份资源(物理内存)。
头文件: #include
原型:int pipe(int fd[2])
参数:文件描述符数组,其中fd[0]表示读端,fd[1]表示写端
成功,返回0。错误返回错误码
int main()
{
int fd[2] = {0};
pipe(fd);
pid_t id = fork();
if(id == 0)//子进程写
{
close(fd[0]);//关闭读操作符
char buf[] = "I'm child";
while(1)
{
write(fd[1], buf, strlen(buf));
sleep(1);
}
}
else//父进程读
{
close(fd[1]);//关闭写操作符
char ret[1024];
while(1)
{
ssize_t s = read(fd[0], ret, sizeof(ret) - 1);
if(s < 0)
{
printf("printf error");
break;
}
else if(s > 0)
{
ret[s] = 0;
printf("parent get child : %s\n", ret);
}
else
{
printf("parent get child : %s\n", ret);
break;
}
}
}
return 0;
}
让我们看看这四种情况:
#include
#include
#include
#include
int main()
{
int fd[2] = {0};
pipe(fd);
pid_t id = fork();
if(id == 0)//子进程写
{
close(fd[0]);
int count = 0;
char buf[] = "I'm child";
while(1)
{
write(fd[1], buf, strlen(buf));
printf("%d\n", count += strlen(buf));
}
}
else//父进程不读
{
close(fd[1]);
waitpid(id, NULL, 0);
}
return 0;
}
结果:进程运行到一定程度,停止(被阻塞)
原因:这个进程被阻塞,不能被调度,不能被运行,由R状态-》非R状态,进程被挂起,将PCB挂到等待队列中。
#include
#include
#include
#include
int main()
{
int fd[2] = {0};
pipe(fd);
pid_t id = fork();
if(id == 0)//子进程写完后关闭
{
close(fd[0]);
int count = 0;
char buf[] = "I'm child";
while(1)
{
write(fd[1], buf, strlen(buf));
printf("%d\n", count += strlen(buf));
close(fd[1]);
sleep(1);//子进程一秒之后关闭
break;
}
}
else//父进程读
{
close(fd[1]);
char ret[1024];
while(1)
{
sleep(1);
ssize_t s = read(fd[0], ret, sizeof(ret) - 1);
if(s < 0)
{
printf("printf error");
break;
}
else if(s > 0)
{
ret[s] = 0;
printf("parent get child : %s\n", ret);
}
else
{
printf("read file end!\n");
break;
}
}
waitpid(id, NULL, 0);
}
return 0;
}
#include
#include
#include
#include
int main()
{
int fd[2] = {0};
pipe(fd);
pid_t id = fork();
if(id == 0)//子进程写
{
close(fd[0]);
int count = 0;
char buf[] = "I'm child";
while(1)
{
write(fd[1], buf, strlen(buf));
printf("%d\n", count += strlen(buf));
sleep(1);
}
}
else//父进程读
{
close(fd[1]);
char ret[1024];
while(1)
{
sleep(1);
ssize_t s = read(fd[0], ret, sizeof(ret) - 1);
if(s < 0)
{
printf("printf error");
break;
}
else if(s > 0)
{
ret[s] = 0;
printf("parent get child : %s\n", ret);
}
else
{
printf("read file end!\n");
break;
}
break;
}
close(fd[0]);
int status = 0;
waitpid(id, &status, 0);//获取信号
printf("sign : %d\n", status & 0x7F);//信号再第7位
}
return 0;
}
结果:子进程退出,父进程读取子进程的退出码
原因:子进程被终止,父进程获得子进程的状态
如果我们想在不相关的进程之间交换数据,就需要用到FIFO文件,被称为命名管道。
#include
#include
int main()
{
mkfifo("ALA", 0644);
return 0;
}
server(服务器端)
#include
#include
#include
#include
#include
#include
#include
int main()
{
umask(0);
mkfifo("ALA", 0644);//创建命名管道
int op = open("ALA", O_RDONLY);//打开匿名管道
char buf[1024];
while(1)
{
printf("wait ....");
ssize_t s = read(op, buf, sizeof(buf) - 1);//从管道中读数据
if(s > 0)
{
buf[s] = 0;
printf("server read : %s", buf);
}
else if(s == 0)
{
printf("client quit!\n");
break;
}
else
{
printf("read error!\n");
break;
}
}
close(op);
return 0;
}
client(客户端)
#include
#include
#include
#include
#include
#include
#include
int main()
{
int op = open("ALA", O_WRONLY);//打开命名管道
char buf[1024];
while(1)
{
printf("Please Enter : ");
fflush(stdout);
ssize_t s = read(0, buf, sizeof(buf) - 1);//从标准输入(键盘中读取数据)
if(s > 0)
{
buf[s] = 0;
write(op, buf, strlen(buf));//读完后,再写入管道中
}
else if(s == 0)
{
printf("client quit!\n");
break;
}
else
{
printf("read error!\n");
break;
}
}
close(op);
return 0;
}
结果:客户端从标准输入(键盘中)读取数据,放入命名管道中。客户端再从命名管道中读取数据,通过Printf打印到电脑屏幕上。