进程间通信--无名管道与有名管道

目录

线程间的通信方式

进程的特点

为什么要进程间通信,进程间通信可以做什么

1.进程间通信方式

2.无名管道

特点

函数接口

注意事项

练习

运行结果

3.有名管道

特点

函数接口

注意事项

4.总结

有名管道和无名管道的区别


线程间的通信方式

全局变量

进程的特点

系统会为每一个进程分配0-4g的虚拟空间,0-3g(用户空间)是每个进程所独有的,3g-4g(内核空间)是所有进程共有的。

CPU调度进程时会给进程分配时间片(几毫秒~十几毫秒),当时间片用完后,cpu再进行其他进程的调度,实现进程的轮转,从而实现多任务的操作。

为什么要进程间通信,进程间通信可以做什么

1).数据传输

一个进程需要将它的数据发送给另一个进程;

2).资源共享

多个进程之间共享同样的资源;

3).通知事件

一个进程需要向另一个或一组进程发送消息,通知它们发生了某种事件;

4).进程控制

有些进程希望完全控制另一个进程的执行(如Debug进程),该控制进程希望能够拦截另一个进程的所有操作,并能够及时知道它的状态改变。

1.进程间通信方式

早期进程间通信:无名管道、有名管道、信号

system V IPC 对象:共享内存、信号灯集、消息队列

BSD:socket

2.无名管道

特点

a.无名只能用于具有亲缘关系的通信。

b.半双工通信,有固定的读端和写端。

(单工:单方向,电视、广播。

半双工:可以双向,同一时刻只能在一个方向。

全双工:可以同一时刻双向。)

c.无名管道可以看作一种特殊的文件,对于他的读写,可以使用文件IO如read、write。

d.无名管道借助文件描述符通信,当管道建立,自动创建两个文件描述符,fd[0]读管道、fd[1]写管道。

函数接口

int pipe(int fd[2])

功能:创建无名管道

参数:文件描述符 fd[0]:读端 fd[1]:写端

返回值:成功 0

失败 -1

注意事项

  1. 当管道中无数据时,读操作阻塞;管道中无数据,将写端关闭,读操作立即返回;
  2. 管道中写满64k时,写阻塞,读出4k空间,写继续;
  3. 只有管道的读端存在,向管道中写数据才有意义,会导致管道破裂,内核发送SIGPIPE信号。

练习

父子进程实现通信,父进程循环从终端输入数据,子进程循环打印,当输入quit结束。

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

int main(int argc, char const *argv[])
{
    int fd[2] = {0};//定义两个文件描述符
    char buf[32] ="";
    int pfd=pipe(fd);
    if (pfd < 0)//1.先创建无名管道
    {
        perror("pipe err");
        return -1;
    }
    printf("fd[0]:%d fd[1]:%d\n", fd[0],fd[1]);//读端、写端
    
    pid_t pid = fork();//2.后创建父子进程,拿到同一个管道
    if(pid<0)
    {
        perror("pipe err");
        return -1;
    }
    else if (pid == 0)
    {
        while (1)
        {
            read(fd[0], buf, 32);
            if (!strcmp(buf, "quit"))
                break;
            printf("buf:%s\n", buf);
        }
    }
    else{
        while (1)
        {
            scanf("%s", buf);
            write(fd[1], buf, 32);
            if (!strcmp(buf, "quit"))
                break;
        }
        wait(NULL);//回收所有的子进程
    }
    close(fd[0]);
    close(fd[1]);
    return 0;
}

运行结果

3.有名管道

特点

  1. 可以使不相干进程进行通信。
  2. 有名管道可以通过路径名指出,在文件系统中可见,但内容存放在内存中。
  3. 文件IO操作有名管道
  4. 遵循先进先出
  5. 不支持lseek()操作。

函数接口

int mkfifo(const char *filename,mode_t mode);

功能:创健有名管道

参数:filename:有名管道文件名

mode:权限

返回值:成功:0

失败:-1,并设置errno号

注意对错误的处理方式:

如果错误是file exist时,注意加判断,如:if(errno == EEXIST)

注意事项

  1. 只写方式,写阻塞,一直到另一个进程把读打开
  2. 只读方式,读阻塞,一直到另一个进程把写打开
  3. 可读可写,若管道中无数据,读阻塞。

4.总结

有名管道和无名管道的区别

无名管道

有名管道

使用场景

亲缘关系

不相关进程

特点

半双工

固定的读端和写端

被看作特殊的文件,通过文件IO进行操作

在文件系统中可见,数据存放在内存

文件IO操作

不支持lseek()操作,遵循先进先出

函数

pipe()

直接read、write

mkfifo()

先open打开,在进行read、write

读写特性

当无名管道无数据,读阻塞

当无名管道中写满64k,写阻塞

读端关闭,继续写数据会造成管道破裂

只写方式,写阻塞,直到另一个进程把读打开

只读方式,读阻塞,直到另一个进程把写打开

可读可写,管道中无数据时,读阻塞

猜你喜欢

转载自blog.csdn.net/m0_68672255/article/details/130394689