Linux進程通訊-管道

來源:互聯網
上載者:User

管道(pipe):用於親緣關係進程間(如父子進程,兄弟進程)的通訊
一個進程寫管道:寫入位元組數小於PIPE_BUF是原子操作,寫操作在管道緩衝區沒有及時讀走時發生阻塞。
一個進程讀管道:讀操作在管道緩衝區沒有資料時發生阻塞。

主要函數:
int pipe(int filedes[2]); 

代碼執行個體建立了父子進程,父進程寫管道,子進程讀管道。
代碼驗證了寫阻塞:子進程讀一次管道就休眠1秒,父進程一次寫操作後將阻塞,直到子進程取走資料。
代碼驗證了讀阻塞:父進程的寫一次管道後休眠1秒,子進程一次讀操作後將阻塞,直到父進程再次寫資料。
如果管道內的實際資料比請求讀的要少,讀不阻塞。

但是無法驗證寫入位元組數大於PIPE_BUF不是原子操作,我想不出一個方法來驗證它。

附代碼

 

#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include<stdlib.h>
main()
{
    int pipe_fd[2];
    pid_t pid;
    int len = 4096*2;
    char r_buf[len];
    char w_buf[len];
    char* p_wbuf;
    int r_num;
    int w_num;
    int cmd;    
    memset(r_buf,0,sizeof(r_buf));
    memset(w_buf,0,sizeof(r_buf));
    p_wbuf=w_buf;
    if(pipe(pipe_fd)<0)
    {
        printf("pipe create error
");
        return -1;
    }
    
    if((pid=fork())==0)
    {
        close(pipe_fd[1]);    
        while(1)
        {
            r_num=read(pipe_fd[0],r_buf,sizeof(r_buf));            
            if(r_num==0)
                break;
            printf(    "讀位元組數:%d
",r_num);
            //sleep(1);//驗證寫阻塞    
        }    
        
        close(pipe_fd[0]);
        printf(    "子進程退出...
");    
    }
    else if(pid>0)
    {
        close(pipe_fd[0]);//關閉讀
        //sleep(5);
        while(1)
        {
            //w_num = write(pipe_fd[1],w_buf,sizeof(w_buf));
            w_num = write(pipe_fd[1],w_buf,111);
            if(w_num!=-1)
                printf(    "寫位元組數:%d
",w_num);    
            else
                printf(    "error
");    
            sleep(1);//驗證讀阻塞    
        }
        close(pipe_fd[1]);//關閉寫
        printf(    "父進程退出...
");    
    }    

}

有名管道(FIFO):與管道不同,可以在沒有親緣關係的多個處理序間通訊。

建立完FIFO,讀或寫FIFO的進程首先要有開啟FIFO的操作:
讀FIFO的進程以阻塞方式讀開啟,如果沒有其它進程寫則開啟操作阻塞;
寫FIFO的進程以阻塞方式寫開啟,沒有其它進程讀則開啟操作阻塞。

某進程以阻塞方式讀FIFO,如果FIFO沒有資料或是有資料但其它進程在讀,則發生阻塞。
某進程以阻塞方式寫FIFO,與寫管道是一樣的,寫入位元組數小於PIPE_BUF是原子操作,
寫操作在管道緩衝區沒有及時讀走資料時發生阻塞。

主要函數:
int mkfifo (const char *pathname, mode_t mode);

附代碼

 

#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include<stdlib.h>
#include<stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#define FIFO "fifo"
main()
{
    pid_t pid;
    int fd_r,fd_w;
    int num_r,num_w;
    int len = 40;
    char buf_r[len];
    char buf_w[len];
    //也可以在shell下用mkfifo建立fifo
    if((mkfifo(FIFO,O_CREAT|O_EXCL)<0)&&(errno!=EEXIST))
    {
        printf("create fifo fail!
");
        return;
    }
    
    if((pid=fork())==0)
    {
        sleep(1);
        printf("進程(%d):準備開啟fifo
",getpid());
        fd_r = open(FIFO,O_RDONLY,0);
        if(fd_r==-1)//以阻塞方式讀開啟,沒有其它進程寫則開啟操作阻塞
        {
            printf("進程(%d):開啟fifo失敗...
",getpid());
            return;
        };
        printf("進程(%d):開啟fifo成功.
",getpid());
        while(1)
        {
            num_r = read(fd_r,buf_r,sizeof(buf_r));
            printf(    "讀位元組數:%d
",num_r);
            sleep(1);
            //這裡將驗證寫阻塞,寫進程不休眠,很快就把管道寫滿,再寫的時候就阻塞了
        }
        
    }
    else if(pid>0)
    {
         
         printf("進程(%d):準備開啟fifo
",getpid());
        //if(open(FIFO,O_WRONLY|O_NONBLOCK,0)==-1)
        fd_w = open(FIFO,O_WRONLY,0);
        if(fd_w ==-1)//以阻塞方式寫開啟,沒有其它進程讀則開啟操作阻塞
        {
            printf("進程(%d):開啟fifo失敗...
",getpid());
            return;
        }
        printf("進程(%d):開啟fifo成功.
",getpid());
        while(1)
        {
            num_w = write(fd_w,buf_w,sizeof(buf_w));
            printf(    "寫位元組數:%d
",num_w);
            
        }
    }       
}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.