C语言:详细介绍了六种进程间通讯方式(还有一种socket在主页关于socket的介绍里面有详细介绍,欢迎观看)

一.无名管道

1.1无名管道的原理

无名管道只能用于亲缘间进程的通信,无名管道的大小是64K。无名管道是内核空间实现的机制。

1.2功能

 1) Pipe()创建一个管道,这是一个单向的数据通道,可用于进程间通信。

2)数组pipefd用于返回两个指向管道末端的文件描述符。

3)Pipefd[0]指的是管道的读端。Pipefd[1]指的是管道的写入端,写入管道的写入端数据由内核进行缓冲(64k),直到从管道的读取端读取为止。

1.3无名管道通信特点

1.只能用于亲缘间进程的通信

2.无名管道数据半双工的通信的方式

​ 单工 : A -------------->B

​ 半双工 : 同一时刻 A----->B B------>A

​ 全双工 : 同一时刻 A<---->B

3.无名管道的大小是64K

4.无名管道不能够使用lseek函数

5.读写的特点

如果读端存在写管道:有多少写多少,直到写满为止(64k)写阻塞

如果读端不存写管道,管道破裂(SIGPIPE) (可以通过gdb调试看现象)

如果写端存在读管道:有多少读多少,没有数据的时候阻塞等待

如果写端不存在读管道:有多少读多少,没有数据的时候立即返回

1.4无名管道的实例

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h> 
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#define ERROR(msg) do{\
    printf("%s %s %d\n", __FILE__, __func__, __LINE__);\
    printf(msg);\
    exit(-1); \
}while(0)

int main(int argc, char const *argv[])
{
    pid_t pid;
    int num[2];
    char buff[128] = {0};

    if (pipe(num)){
        ERROR("pipe error");
    }

    if ((pid = fork()) == -1){
        ERROR("fork error");
    }else if(pid == 0){
        close(num[0]);
        while (1){
            memset(buff, 0, sizeof(buff));
            printf("请输入您要输入的数值>>");
            fgets(buff, sizeof(buff), stdin);
            buff[strlen(buff) -1] = '\0';
            write(num[1], buff, strlen(buff));

            if (!strncmp(buff, "quit", 4)){
                break;
            }

        }
        close(num[1]);
        exit(EXIT_SUCCESS);
    }else{
        close(num[1]);
        while (1){
            memset(buff, 0, sizeof(buff));
            read(num[0], buff, sizeof(buff));

            if (!strncmp(buff, "quit", 4)){
                break;
            }
            printf("%s\n",buff);
        }   
        close(num[0]);
        wait(NULL);
    }

    return 0;
}

二.有名管道

2.1有名管道的原理

1)可以用于亲缘间进程的通信,也可以用于非亲缘间的进程的通信。

2)有名管道会创建一个文件,需要通信的进程打开这个文件,产生文件描述符后就可以通信了,有名管道的文件存在内存上。

3)有名管道的大小也是64K,也不能使用lseek函数

2.2有名管道的特点

1.可以用于任意进程间的通信

2.有名管道数据半双工的通信的方式

3.有名管道的大小是64K

4.有名管道不能够使用lseek函数

5.读写的特点

如果读端存在写管道:有多少写多少,直到写满为止(64k)写阻塞

如果读端不存写管道

​ 1.读权限没有打开,写端在open的位置阻塞

​ 2.读端打开后关闭,管道破裂(SIGPIPE) (可以通过gdb调试看现象)

如果写端存在读管道:有多少读多少,没有数据的时候阻塞等待

如果写端不存在读管道

​ 1.写权限没有打开,读端在open的位置阻塞

​ 2.写端打开后关闭,有多少读多少,没有数据的时候立即返回

2.3有名管道实例:

mkfifo文件:

#include <stdio.h>
#include <stdlib.h>
#define ERROR(msg) do{\
    printf("%s %s %d\n", __FILE__, __func__, __LINE__);\
    printf(msg);\
    exit(-1); \
}while(0)

int main(int argc, char const *argv[])
{
    if (mkfifo("./fifo",0666)){
        ERROR("mkfifo error");
    }

    //有名管道没有阻塞,手动加一个阻塞
    getchar();

    system("rm ./fifo -rf");
    
    return 0;
}

write文件:

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

#define ERROR(msg) do{\
    printf("%s %s %d\n", __FILE__, __func__, __LINE__);\
    printf(msg);\
    exit(-1); \
}while(0)

int main(int argc, char const *argv[])
{
    int fd;
    char buff[128] = {0};
    if ((fd = open("./fifo",O_WRONLY)) == -1){
        ERROR("open fifo error\n");
    }

    while(1){
        printf("input >");
        fgets(buff, sizeof(buff), stdin);
        buff[strlen(buff) - 1] = '\0';

        write(fd, buff, strlen(buff));
        if(!strncmp("quit",buff,4))break;
    }
    close(fd);
    return 0;
}

read文件:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值