無名管道的特點:
1.適用場景:只能用於具有親緣關係的兩個進程之間;
2.通信模式:半雙工模式,具有固定的讀端(0)和寫端(1);
3.讀寫方式:用文件io,不支持lseek;
4.讀阻塞:當管道中無數據時;
寫阻塞:當管道中寫滿數據時;
5.管道大小:無名管道大小64k;
6.管道破裂:關閉讀端,仍然想管道中寫入數據時;
對管道進行寫的進程會收到內核發來SIGPIPE的信號,可以捕獲;
來,我們用無名管道先寫一個回顯程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define N 32
int main(int argc, const char *argv[])
{
int pipefd[2];
int pid;
if(pipe(pipefd) < 0)
{
perror("pipe error");
exit(1);
}
if( (pid = fork()) < 0)
{
perror("fork error");
exit(1);
}
else if(pid == 0)
{
char buf[N];
int ret;
close(pipefd[0]);
puts("im chd start");
while(fgets(buf, N, stdin) != NULL)
{
write(pipefd[1], buf, N);
if(strncmp(buf, "quit", 4) == 0)
{
break;
}
}
puts("im chd end");
exit(2);
}
else if(pid > 0)
{
int chdstatus, out_pid, ret;
char buf[N];
close(pipefd[1]);
puts("im farther start");
//父進程在這裏會阻塞,應爲管道的特點中有一條“當管道中無數據時,會讀阻塞”,
//程序啓動時,如果父進程現將佔到系統資源執行到這裏仍然會阻塞,因爲管道中沒
//有數據。所以父進程要想執行,必須依賴於子進程向管道中寫入數據;
//但是如果是讀取一個文件,文件爲空,此時read等於0,則不會執行while循環;
//在這裏主要提一下管道無數據,會讀阻塞;
while(read(pipefd[0], buf, N) > 0)
{
puts("im if");
if(strncmp(buf, "quit", 4) == 0)
{
exit(1);;
}
fputs(buf, stdout);
}
puts("im farther end");
out_pid = waitpid(pid, &chdstatus, 0);
printf("outpid = %d\n", out_pid);
if(WIFEXITED(chdstatus))
{
printf("exit_num = %d\n", WEXITSTATUS(chdstatus));
}
exit(0);
}
return 0;
}
下面我們用無名管道來實現一個文件服務器的功能