進程學習:進程間通信(傳統通信方式)1.無名管道

無名管道的特點:

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;
}

下面我們用無名管道來實現一個文件服務器的功能

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章