#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
#include<stdlib.h>
int main()
{
int fd[2] = {0, 0};
//創建管道,將寫端和讀端的文件描述符分別放入fd[1],fd[0]
if(pipe(fd) < 0)
{
perror("pipe: ");
return -1;
}
pid_t id = fork();
if(id == 0)//子進程向管道中寫入
{
//關閉子進程的讀端
close(fd[0]);
char *msg = "Hello,I am child\n";
while(1)
{
//向管道中寫入內容
write(fd[1], msg, strlen(msg));
sleep(1);
}
}
else//父進程從管道中讀取
{
//關閉父進程的寫端
close(fd[1]);
char buf[1024];
while(1)
{
//從管道中讀出內容
ssize_t s = read(fd[0],buf,sizeof(buf)-1);
if(s > 0)
{
buf[s] = 0;
printf("father read: %s", buf);
}
}
}
}
- 單向通信
- 只能進行具有血緣關係的進程間通信,常用於父子進程
- 管道生命週期隨進程
- 管道提供面向字節流的通信服務
- 自帶同步機制,保證讀寫的正確性
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
int main()
{
//創建命名管道
if(mkfifo("./mypipe", S_IFIFO|0666) < 0)
{
perror("mkfifo :");
return -1;
}
//代開管道文件,讀方式打開
int fd = open("./mypipe", O_RDONLY);
if(fd < 0)
{
perror("open :");
return -2;
}
//緩衝
char buf[1024];
while(1)
{
//從管道輸入讀內容到緩衝
ssize_t s = read(fd, buf, sizeof(buf)-1);
if(s > 0)
{
buf[s] = 0;
//從緩衝寫到標準輸出
write(0,buf,strlen(buf));
}
else if(s == 0)
{
break;
}
}
close(fd);
return 0;
}
client:
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
int main()
{
//代開管道文件,寫方式打開
int fd = open("./mypipe", O_WRONLY);
if(fd < 0)
{
perror("open :");
return -2;
}
//緩衝
char buf[1024];
while(1)
{
//從標準輸入讀內容到緩衝
ssize_t s = read(0, buf, sizeof(buf)-1);
if(s > 0)
{
buf[s] = 0;
//從緩衝寫到管道中
write(fd,buf,strlen(buf));
}
else if(s == 0)
{
break;
}
}
close(fd);
return 0;
}
【使用管道時需要注意的四種情況】
- 如果指向管道寫端的文件描述符被關閉,那麼當其他進程繼續從讀端讀取數據時,管道中剩下的數據被取走之後在繼續讀取數據會直接返回0,類似於讀到文件末尾。
- 如果指向管道寫端的文件描述符沒有關閉,但是進程並不往其中寫入內容,當其他進程繼續從讀端讀取數據時,管道中剩下的數據被讀取之後在進行讀會read阻塞,直到管道中寫入新的數據。
- 如果指向管道讀端的文件描述符沒有關閉,但是進程並不讀任何內容,當其他進程繼續從寫端寫入時,當管道中剩下的空間被寫滿在次寫入會write阻塞,直到管道中的數據被讀走。
- 如果指向管道讀端的文件描述符被關閉,當寫端進程繼續向管道中寫數據時,操作系統會向寫端的進程發送13號信號,導致進程異常結束。