1. 程式人生 > >程序間通訊的方式簡單解析————管道

程序間通訊的方式簡單解析————管道

本人最近學習了程序間通訊,並看了一些博文,然後結合書籍根據自己的理解寫了這篇文章。

1. 管道

函式原型:經由引數fd返回兩個檔案描述符:fd[0]為讀,fd[1]為寫。fd[1]的輸出是fd[0]的輸入。

#include <unistd.h>
	int pipe(int fd[2]);

侷限性:

(1)歷史上,它是半雙工的,某些系統提供全雙工管道,即其可移植性並不好。
(2)它只能在具有公共祖先的兩個程序間使用。

示例程式碼:

#include <stdio.h>
#include <unistd.h>
#include <error.h>
#include
<string.h>
int main(){ int pipe_fd[2]; int ret = pipe(pipe_fd);//類似兩個檔案指標,針對管道中的讀(0)和寫(1) if(ret == -1){ printf("建立管道失敗,錯誤碼是:%d,%d\n",error,strerror(error)); return 0; } pid_t pid = fork();//建立子程序 if(pid < 0){ printf("建立子程序錯誤\n"); return
0; } else if(pid == 0){ //子程序的操作 close(_pipe[0]); // 關閉讀通道 int i = 0; char sendbuf[BUFSIZ]; while( i < 20){ scanf("%s", sendbuf); write(pipe_fd[1], sendbuf, strlen(sendbuf)); sleep(2); i++; } } else
{ //進入父程序,從子程序讀取資料 close(pipe_fd[1]); //關閉寫通道 char recv[BUFSIZ]; while(1){ memset(recv, 0, sizeof(recv)); int length= read(pipe_fd[0], recv, sizeof(recv)); if(strstr(recv, "quit") != 0){ printf("退出程式\n"); exit(0); } printf("message:%s. length:%d.\n", recv, length); } if(waitpid(pid, NULL, 0) < 0){ //避免父程序與子程序衝突,讓子程序先執行 return 0; } } return 0; }

執行結果:

在這裡插入圖片描述

2. 命名管道(FIFO)

函式原型:

#include<sys/stat.h>
	int mkfifo(const char *path, mode_t mode);
	int mkfifoat(int fd, const char *path, mode_t mode);

引數資訊:

(1)引數fd為檔案描述符。
(2)引數path為路徑名。
(3)mode引數指定檔案的訪問許可權位。

FIFO的用途:

(1)shell命令使用FIFO將資料從一條管道傳送到另一條時,無需建立中間臨時檔案。
(2)C/S應用程式中,FIFO用作匯聚點,在二者之間傳遞資料。

示例程式碼:fifo-read.c

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>                                                                                                                                                                                                                                  
#include <sys/types.h>
#include <sys/stat.h>

#define _PATH_ "/tmp/file.fifo"

int main(){
    int fd = open(_PATH_, O_RDONLY);//以只讀的許可權開啟檔案
    if(fd < 0){ 
        printf("開啟失敗\n");
        return 0;
    }   
    char recv[BUFSIZ];
    while(1){
        memset(recv, 0, sizeof(recv));//字串清零
        int ret = read(fd, recv, sizeof(recv));
        if(strstr(recv, "quit") != 0){ //判斷接收到的字元是否是quit
            printf("退出程式\n");
            exit(0);
        }   
        printf("message:%-20s. length:%d\n", recv, ret);
    }   

    close(fd);//關閉檔案
    return 0;
}

執行結果:

在這裡插入圖片描述

fifo-write,c

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

#define _PATH_ "/tmp/file.fifo"

int main(){
    int ret = mkfifo(_PATH_, 0666);//建立管道檔案
    if(ret == -1){
        printf("建立管道失敗\n");
        exit(0);
    }   
    int fd = open(_PATH_, O_WRONLY);//以只寫的許可權開啟檔案
    if(fd < 0){ 
        printf("開啟失敗\n");
        exit(0);
    }   
    char buf[BUFSIZ];
    while(1){
        memset(buf, 0, strlen(buf));//字串清零
        printf("please input the string:");
        scanf("%s", buf);
        int ret = write(fd, buf, strlen(buf));//寫資料
        if(ret < 0){ 
            printf("寫出錯\n");
            break;
        }   
        if(strstr(buf, "quit") != 0){ 
            break;
        }   
    }   

    close(fd);//關閉檔案
    unlink(_PATH_);//刪除管道檔案
    return 0;
}

執行結果:

在這裡插入圖片描述