linux IPC總結——管道

管道linux

管道是unix ipc的最古老形式,是一種在內存中的特殊文件,只能在具備公共祖先的進程之間使用(即父子進程,兄弟進程)。ios

管道由pipe函數建立函數

#include <unistd.h>

int pipe(int fd[2])

fd[1]寫,fd[0]讀。spa

單個進程的管道幾乎沒有任何用處,一般,調用pipe的進程接着調用fork,這樣就建立了父子進程間的管道。unix

#include <unistd.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/wait.h>

int main()
{
    int fd[2];
    char buf[80];
    pid_t pid;
    pipe(fd);
    pid = fork();
    if(pid>0)
    {//父進程
        printf("Father thread\n");
        char s[]="Hello\n";
        write(fd[1],s,sizeof(s));
        close(fd[0]);
        close(fd[1]);
    }
    else if(pid==0)
    {
        printf("Child Thread\n");
        read(fd[0],buf,sizeof(buf));
        printf("%s\n",buf);
        close(fd[0]);
        close(fd[1]);
    }
    waitpid(pid,NULL,0);//等待子進程結束
    return 0;
}

 輸出結果:code

Father thread
Child Thread
Helloblog

當管道的一端關閉時:進程

  當讀一個寫端關閉的管道時,則認爲已經讀到了數據的末尾,讀函數返回的讀出字節數爲0;ip

  當寫一個讀端關閉的管道時,向管道中寫入數據的進程將收到內核傳來的SIFPIPE信號,應用程序能夠處理該信號,也能夠忽略(默認動做則            是應用程序終止)。內存

從管道中讀取數據:

當管道的寫端存在時,若是請求的字節數目大於PIPE_BUF,則返回管道中現有的數據字節數,若是請求的字節數目不大於PIPE_BUF,則返回管道中現有數據字節數(此時,管道中數據量小於請求的數據量);或者返回請求的字節數(此時,管道中數據量不小於請求的數據量)。注:PIPE_BUF在include/linux/limits.h中定義。

向管道中寫入數據:

向管道中寫入數據時,linux將不保證寫入的原子性,管道緩衝區一有空閒區域,寫進程就會試圖向管道寫入數據。若是讀進程不讀走管道緩衝區中的數據,那麼寫操做將一直阻塞。 

管道由於沒有名字因此只能用於具備親緣關係的進程,而有名管道(FIFO)則克服了這個限制。

FIFO

建立函數以下

 #include <sys/types.h>
 #include <sys/stat.h>

 int mkfifo(const char *pathname, mode_t mode);

 第一個參數是一個普通的路徑名,即爲FIFO的名字。第二個參數設置權限,跟建立普通文件同樣。

FIFO的讀寫也像普通文件同樣,不過須要讀寫端都打開,具體規則以下:

當打開(open)時:

若沒有設置O_NONBLOCK,只讀open要阻塞到其它進程爲寫而打開FIFO。相似地,只寫open要阻塞到其它進程爲讀而打開FIFO。

若是設置了O_NONBLOCK,則只讀open當即返回,若沒有其它進程爲寫而打開FIFO,則返回-1。

用FIFO模擬生產者消費者問題:

fifo2.cpp:

#include<iostream>
#include<unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include<limits.h>
#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


#define FIFO "/tmp/myfifo"
#define BUF_SIZE PIPE_BUF
#define SEND_MAX (1024*1024*10)
using namespace std;

int main()
{
    int pid,fifo_fd;
    int send_num;
    char *buf[BUF_SIZE+1];
    if(-1 == access(FIFO,F_OK))
    {
        int res = mkfifo(FIFO,0777);
        if(res != 0)
        {
            fprintf(stderr,"can't create fifo in %s",FIFO);
            exit(EXIT_FAILURE);
        }
    }

    fifo_fd = open(FIFO,O_WRONLY);
    printf("process %d open fifo %d\r\n",getpid(),fifo_fd);
    if(fifo_fd == -1)
        exit(EXIT_FAILURE);
    int res;
    while(send_num<SEND_MAX)
    {
        res = write(fifo_fd,buf,BUF_SIZE);
        if(res == -1)
        {
            cout<<"write fifo error"<<endl;
            exit(EXIT_FAILURE);
        }
        send_num += res;
    }
    return 0;
}

 fifo3.cpp

#include<iostream>
#include<unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include<limits.h>
#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


#define FIFO "/tmp/myfifo"
#define BUF_SIZE PIPE_BUF
#define SEND_MAX (1024*1024*10)
using namespace std;

int main()
{
    int fifo_fd;
    int res;
    char buffer[BUF_SIZE+1];
    int read_num = 0;

    fifo_fd = open(FIFO,O_RDONLY);
    printf("process %d open FIFO %d\r\n",getpid(),fifo_fd);
    if(fifo_fd == -1)
        exit(EXIT_FAILURE);
    do{
        res = read(fifo_fd,buffer,BUF_SIZE);
        read_num += res;
    }while(res>0);
    close(fifo_fd);
    return 0;
}

結果以下:

可見讀進程運行0.013s就讀取了10m的數據,FIFO的效率仍是很高的。

相關文章
相關標籤/搜索