进程间通信----管道

本文深入探讨了管道通信机制,包括匿名管道和命名管道的工作原理及使用方法。通过具体实例展示了如何利用管道实现进程间的通信,特别关注了不同打开模式对管道通信的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.思维导图
这里写图片描述

注意:
管道都是单向传递数据的。
匿名管道:

  • filedes[0]用于读出数据,读取时必须关闭写入端,即close(filedes[1]);
    filedes[1]用于写入数据,写入时必须关闭读取端,即close(filedes[0])。

命名管道:
打开FIFO文件通常有几种方式:

open(const char *path, O_RDONLY); 
open(const char *path, O_RDONLY | O_NONBLOCK); 
open(const char *path, O_WRONLY);
open(const char *path, O_WRONLY | O_NONBLOCK);

O_NONBLOCK:open调用是非阻塞的;否则,open调用是阻塞的。

对于以只读方式(O_RDONLY)打开的FIFO文件,如果open调用是阻塞的(即第二个参数为O_RDONLY),除非有一个进程以写方式打开同一个FIFO,否则它不会返回;如果open调用是非阻塞的的(即第二个参数为O_RDONLY | O_NONBLOCK),则即使没有其他进程以写方式打开同一个FIFO文件,open调用将成功并立即返回。

对于以只写方式(O_WRONLY)打开的FIFO文件,如果open调用是阻塞的(即第二个参数为O_WRONLY),open调用将被阻塞,直到有一个进程以只读方式打开同一个FIFO文件为止;如果open调用是非阻塞的(即第二个参数为O_WRONLY | O_NONBLOCK),open总会立即返回,但如果没有其他进程以只读方式打开同一个FIFO文件,open调用将返回-1,并且FIFO也不会被打开。
2.匿名管道实例:

#include<stdio.h>  
#include<unistd.h>  
#include<errno.h>  
#include<string.h>  
#include<sys/wait.h>  

int main()  
{  
    //创建一个保存管道的数组,并创建匿名管道
    int my_pipe[2];  
    int ret = pipe(my_pipe);  
    if (ret == -1) {  
        printf("creare pipe error\n");  
        return -1;  
    }  


    pid_t id = fork();  
    if (id < 0) {  
        printf("fork error\n");  
        return -1;  
    } 

    if (id == 0) {  
        //关闭子进程读端
        close(my_pipe[0]);  
        int i = 0;  
        char* mesg_c = NULL;  
        while (i++ < 10) {  
            mesg_c = "i am a child!";  
            write(my_pipe[1],mesg_c,strlen(mesg_c)+1);  
            sleep(1);  
        }  
        close(my_pipe[1]);  
    }  else  {  
        //关闭父进程写端
        close(my_pipe[1]);  
        char _mesg[100];  
        int j = 0;  
        while (j++ < 100) {  
            memset(_mesg,'\0',sizeof(_mesg));  
            int ret = read(my_pipe[0],_mesg,sizeof(_mesg));  
            printf("%s:code is :%d\n",_mesg,ret);  
        }  

        if (waitpid(id,NULL,0) < 0)  
            return -1;  
    }  
    return 0;  
}  

3.命名管道实例:

/*命名管道写进程*/
#include<stdio.h>  
#include<sys/types.h>  
#include<sys/stat.h>  
#include<unistd.h>  
#include<fcntl.h>  
#include<string.h>  

#define PATH "./myfifo"  
#define SIZE 100  

int main()  
{  
    char buf[SIZ_];  
    memset(buf, '\0', sizeof(buf));  

    //创建命名管道
    int ret = mkfifo(PATH, 0666|S_IFIFO);  
    if (ret == -1) {  
        perror("mkfifo error!");  
        return 1;  
    }  

    int fd = open(PATH, O_WRONLY);  
    if (fd<0) {  
        printf("open file error!\n");  
        return 2;  
    }  

    while (1) {  
        read(0, buf, sizeof(buf));  
        int ret = write(fd, buf, strlen(buf)-1);  
        buf[ret] = '\0';  
        if (ret < 0) {  
            printf("wirte error!\n");  
            break;  
        }     
        if(strncmp(buf, "quit", 4) == 0) {  
            break;  
        }  
    }  
    close(fd);  
    return 0;  
}  


/*命名管道读进程*/
#include<stdio.h>  
#include<sys/types.h>  
#include<sys/stat.h>  
#include<unistd.h>  
#include<fcntl.h>  
#include<string.h>  

#define PATH "./myfifo"  
#define SIZE 100  

int main()  
{  
    char buf[_SIZE_];  
    memset(buf, '\0', sizeof(buf)); 

    int fd = open(PATH, O_RDONLY);  
    if (fd < 0) {  
        printf("open file error!\n");  
        return 1;  
    } 

    while (1) {  
        int ret = read(fd, buf, sizeof(buf));  
        if (ret <= 0) {  
            printf("read end or error!\n");  
            break;  
        }  
        printf("%s\n", buf);  
        if (strncmp(buf, "quit", 4)==0) {  
            break;  
        }  
    }  
    close(fd);  
    return 0;  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值