进程间通信、无名管道、有名管道

一、进程

1.1 进程间通信的概念

线程通信通过全局变量即可。

进程间通信是相互独立的,但是所有进程都共用一份内核空间,所以进程和进程之间的通信可以通过内核去进行。

1.2 进程间通信方式

共7种:

  1. 传统的进程间通信方式:
    1. 无名管道
    2. 有名管道
    3. 信号
  2. systemV版本的IPC进程间通信:
    1. 消息队列
    2. 共享内存
    3. 信号灯集
  3. BSD版本的:
    1. socket实现本地通信

1.3 无名管道

1.3.1 无名管道的概念和特性

无名管道在内核中开辟一块内存空间,用于进程间的通信。

无名管道创建之后,回想用户返回两个文件描述符,一个读端文件描述符,一个写端文件描述符。读端文件描述符,用于从管道中读取数据,写端文件描述符,用于向管道中写入数据。

无名管道只能用于亲缘间进程的通信。

无名管道大小是64K。

1.3.2 无名管道的API

cpp 复制代码
#include <unistd.h>
int pipe(int pipedf[2]);
功能:创建一个无名管道
参数:
    pipefd:保存内核返回的管道的两端
        pipedf[0]:管道的读端
        pipedf[1]:管道的写端
返回值:成功返回0,失败返回-1,置位错误码

1.3.3 无名管道运行实例:

cpp 复制代码
#include <my_head.h>

int main(int argc,const char *argv[]){
    int ret = 0;
    int pipedf[2] = {0};
    //创建无名管道
    ret = pipe(pipedf);
    if(-1 == ret){
        PRINT_ERR("create pipe error");
    }
    //创建子进程
    ret = fork();
    if(-1 == ret){
        PRINT_ERR("fork error");
    }
    else if(0 == ret){
        //子进程,关闭读
        char send_buf[128] = {0};
        close(pipedf[0]);
        while(1){
            fgets(send_buf,sizeof(send_buf),stdin);
            send_buf[strlen(send_buf)-1] = '\0';
            write(pipedf[1],send_buf,strlen(send_buf));
            if(!strcmp(send_buf,"quit"))
            break;
        }
        close(pipedf[1]);
    }else{
        //父进程,关闭写
        char recv_buf[128] = {0};
        close(pipedf[1]);
        while(1){
            memset(recv_buf,0,sizeof(recv_buf));
            read(pipedf[0],recv_buf,sizeof(recv_buf));
            if(!strcmp(recv_buf,"quit"))
            break;
            printf("我是父进程,我收到了数据[%s]\n",recv_buf);
        }
        close(pipedf[0]);
        wait(NULL);
    }

    return 0;
}

运行结果:

无名管道的读写特点:

如果读端关闭,向管道写数据:

管道破裂,祥管道写入数据的进程会收到管道破裂的信号,这个信号会杀死该进程。

如果独断打开(不读),一直写:

有多少写多少,管道满了之后(管道大小是164K),会在write的地方阻塞

如果写端不存在,读数据:

如果管道中有数据,就读数据,如果没有数据就立即返回。

如果写端存在(不写),读数据,有数据就读数据,没数据就在read的地方阻塞

1.4有名管道

1.4.1 有名管道的特点

有名管道在内核中开辟一块内存空间,用于进程间的通信。

有名管道创建之后,会在文件系统中创建一个管道文件。

两个进程想要进行通信的时候,可以通过open函数1打开管道文件,然后向管道中写入内容,或者读取内容,实现进程间的通信。

这个管道文件本质上是保存在内存上的。

有名管道可以用于任意进程间通信。

有名管道大小为64K。

2.4.2 创建有名管道的API

cpp 复制代码
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname,mode_t mode);
功能:创建一个有名管道
参数:
    pathname:管道文件的路径和名字
    mode:创建文件的权限(mode & ~umask)
返回值:成功返回0,失败返回-1,置位错误码

mkfifo 管道文件名 --- 通过命令创建一个有名管道

1.4.3 有名管道使用示例

mkfifo.c

cpp 复制代码
#include <my_head.h>

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

    getchar();

    //system("rm fifo");
    remove("./fifo");//删除文件
    return 0;
}

read.c

cpp 复制代码
#include <my_head.h>

int main(int argc,const char *argv[]){
    int fd = 0;
    //1.打开管道文件,以只读的方式打开
    fd = open("./fifo",O_RDONLY);
    if(-1 == fd){
        PRINT_ERR("open fifo error");
    }
    char recv_buf[128] = {0};

    //2.开始循环读
    while(1){
        memset(recv_buf,0,sizeof(recv_buf));
        read(fd,recv_buf,sizeof(recv_buf));
        if(!strcmp(recv_buf,"quit"))
            break;
            printf("读到了数据[%s]\n",recv_buf);
    }
    close(fd);
    return 0;
}

write.c

cpp 复制代码
#include <my_head.h>

int main(int argc,const char *argv[]){
    int fd = 0;
    //1.以只读方式打开管道文件
    fd = open("./fifo",O_WRONLY);
    if(-1 == fd){
        PRINT_ERR("open fifo error");
    }
    char send_buf[128] = {0};
    //2.开始循环写 
    while(1){
        fgets(send_buf,sizeof(send_buf),stdin);
        send_buf[strlen(send_buf) - 1] = '\0';
        write(fd,send_buf,strlen(send_buf));
        if(!strcmp(send_buf,"quit"))
        break;
    }
    close(fd);
    return 0;
}

有名管道的读写特点:

如果读端没有打开,写管道:

在open的位置阻塞。

如果读端打开(不读),写管道:

有多少写多少,写满为止,写阻塞。

读端打开后关闭,写管道:

管道破裂,向写管道的进程发送管道破裂信号,杀死该进程。

如果写端没打开,读管道:

在open的位置阻塞。

写端打开(不写),读管道:

有数据就读数据,没数据,在read的地方阻塞。

写端打开后关闭,读管道:

有数据就读数据,没数据就立即返回。

相关推荐
QQ__176461982431 分钟前
Ubuntu系统创建新用户与删除用户
linux·运维·服务器
渣渣盟1 小时前
Linux邮件服务器快速搭建指南
linux·服务器·开发语言
6极地诈唬1 小时前
【PG漫步】DELETE不会改变本地文件的大小,VACUUM也不会
linux·服务器·数据库
ArrebolJiuZhou1 小时前
00 arm开发环境的搭建
linux·arm开发·单片机·嵌入式硬件
谷雨不太卷1 小时前
Linux_文件权限
linux·运维·服务器
无泪无花月隐星沉2 小时前
uos server 1070e lvm格式磁盘扩容分区
linux·运维·uos
食咗未3 小时前
Linux USB HOST EXTERNAL STORAGE
linux·驱动开发
食咗未3 小时前
Linux USB HOST HID
linux·驱动开发·人机交互
Xの哲學3 小时前
Linux SLAB分配器深度解剖
linux·服务器·网络·算法·边缘计算
齐鲁大虾4 小时前
UOS(统信操作系统)如何更新CUPS(通用Unix打印系统)
linux·服务器·chrome·unix