管道的基本概述及其特性
管道是Unix中最古老的程序間通信的形式。 我們把從一個程序連接配接到另一個程序的一個資料流稱為一個“管道”
特性:半雙工通信---可以選擇方向的單向通信。
本質:在核心中開辟的一段緩沖區(核心空間中的一塊記憶體)
原理:多個程序通過通路同一塊核心中的緩沖區實作通信
分類:
匿名管道:緩沖區沒有辨別符,隻能用于具有親緣關系的程序間通信
命名管道:緩沖區具有辨別符(在檔案系統中會顯示一個管道檔案),可用于同一主機上任意的程序間通信。
匿名管道
管道的建立
函數原型
#include <unistd.h>
int pipe(int pipefd[2]);
pipefd[0]:用于讀
pipefd[1]:用于寫
傳回值:成功傳回0 失敗傳回-1;。
父子程序間實作匿名管道通信
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
int main()
{
int pipefd[2];
int ret = pipe(pipefd);
if (ret < 0)
{
perror("pipe");
return -1;
}
ret = fork();
if (ret < 0)
{
perror("fork");
return -1;
}
else if (ret == 0)
{
//child read
close(pipefd[1]);
char buf[1024] = {0};
ret = read(pipefd[0], buf, 1023);
if (ret < 0)
{
perror("read");
return -1;
}
printf("child read:%s\n", buf);
close(pipefd[0]);
}
//父程序 write
close(pipefd[0]);
printf("father write:");
char buf[128] = {0};
fgets(buf, 127, stdin);
write(pipefd[1], buf, strlen(buf));
close(pipefd[1]);
wait(NULL);
return 0;
}
命名管道
命名管道的辨別符就是一個可見于檔案系統的管道類型檔案。 多個程序通過打開同一個管道檔案,通路同一塊核心中的緩沖區實作通信,當mkfifo一個管道檔案後 核心不會立刻開辟記憶體 而是等到進行讀寫操作的時候會進行記憶體開辟。
指令操作:mkfifo filename 建立一個命名管道檔案
函數操作:int mkfifo(const char *pathname, mode_t mode);
mode 建立權限
傳回值 成功傳回0 失敗傳回-1;
建立一個命名管道進行程序間通信
//write.c
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
int main()
{
int ret = mkfifo("./test.fifo", 0664);
if (ret < 0 && errno != EEXIST)
{
perror("mkfifo");
return -1;
}
int fd = open("./test.fifo", O_WRONLY);
if (fd < 0)
{
perror("open");
return -1;
}
printf("creat fifo!!\n");
char buf[1024] = {0};
while (1)
{
//sprintf(buf,"%s",stdin);
//scanf("%s",buf);
fgets(buf,1023,stdin);
ret = write(fd, buf, strlen(buf));
if(ret<0)
{
perror("write");
return -1;
}
}
close(fd);
return 0;
}
//read.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <memory.h>
int main()
{
int ret = mkfifo("./test.fifo", 0664);
if (ret < 0 && errno != EEXIST)
{
perror("mkfifo");
return -1;
}
int fd = open("./test.fifo", O_RDONLY);
if (fd < 0)
{
perror("open");
return -1;
}
printf("creat fifo!!\n");
char buf[1024] = {0};
while (1)
{
ret = read(fd, buf, 1023);
if (ret < 0)
{
perror("read");
return -1;
}
printf("%s\n", buf);
memset(buf, 0, 1024);
}
close(fd);
return 0;
}
管道的讀寫特性
匿名管道
特性:隻能用于具有親緣關系的程序間通信 因為緩沖區沒有辨別符,無法被其它程序找到,隻能通過子程序父程序的方式擷取到操作句柄實作通信。
讀寫特性:若管道中沒有資料則read會阻塞,若管道中資料滿了,則write會阻塞。
所有的管道讀端被關閉,則繼續write則會觸發異常導緻程序崩潰退出 哪個程序去寫資料哪個程序就會崩潰(原因會給程序發送SIGPIPE信号)。
所有的管道寫端被關閉,則繼續read則會讀完資料後傳回0,不再阻塞。
管道提供位元組流傳輸服務:有序的,可靠的,基于連接配接的流式傳輸。
命名管道
打開特性:若是以隻讀方式打開管道檔案則會阻塞,直到管道被其它程序以寫的方式打開 則會繼續,反之亦是如此。
特性:半雙工通信 可以選擇方向的單向通信
管道提供位元組流傳輸服務 ---- 有序的 可靠的 基于連接配接的一種流式傳輸
基于連接配接:所有read關閉則write異常,所有write關閉則read傳回
互斥的展現:對管道進行寫入操作大小不超過PIPE_BUF-4096大小,則保證操作的原子性
同步的展現:若管道沒有資料則read阻塞 若管道資料滿了 則write阻塞。
生命周期随程序---不人為幹預,所有打開管道的程序退出了後則管道緩沖區被釋放。
同步與互斥
互斥:同一時間程序對臨界資源的唯一通路實作通路操作安全
同步:通過一些條件判斷讓程序對臨界資源的通路更加合理有序
臨界資源:公共資源,大家都能通路到的資源
臨界區:對臨界資源通路的這段代碼區域