linux学习记录(十)------进程间的通信(管道通信)


1.IPC

Inter Process Communication

进程间通信常用的几种方式

1.管道通信:有名管道,无名管道

2.信号- 系统开销小

3.消息队列-内核的链表

4.信号量-计数器

5.共享内存

6.内存映射

7.套接字

2.无名管道

2.1.管道的概念
  • 本质

    • 内核缓冲区
    • 伪文件-不占用磁盘空间
  • 特点:

    • 两部分:
      • 读端,写端,对应两个文件描述符
      • 数据写端流入,读端流出
    • 操作管理的进程被销毁之后,管道自动被释放
    • 管道默认是阻塞的
2.2.管道的原理
  • 内部实现方式:队列
    • 环形队列------>便于数据读取
    • 特点:先进先出
  • 缓冲区大小
    • 默认4K
    • 大小会根据实际情况做适当调整
2.3管道的局限性
  • 队列:
    • 数据只能读取一次,不能重复读取
  • 半双工:
    • 单工:遥控器
    • 半双工:对讲机
      • 数据传输方向是单向的
    • 双工
  • 匿名管道
    • 适用于有血缘关系的进程
2.4.创建匿名管道
int pipe(int fd[2])
fd‐传出参数:
fd[0]‐读端----3
fd[1]‐写端----4
返回值:
0:成功
‐1:创建失败
2.5.父子进程使用管道通信
  • 实现 ps aux| grep “bash”

  • 数据重定向:dup2

2.6.管道的读写行为
  • 读操作

    • 有数据
      • read(fd[1])正常读,返回读的字节数
    • 无数据
      • 写端被全部关闭,read返回0,相当于文件被读到尾部
      • 写端未被全部关闭
        • read被阻塞
  • 写操作

    • 读端被全部关闭
      • 管道破裂,进程被终止(就如同水管一端不停地进水另一端不出水水管迟早被撑爆)
        • 内核给当前进程发送信号SIGPIPE-13,默认处理动作
    • 读端未被全部关闭
      • 缓冲区写满了
        • writezuse
      • 缓冲区未写满
        • write继续写,直到写满为止
  • 如何设置非阻塞?

    • 默认读写两端都阻塞
    • 设置读端为非阻塞pipe(fd)
      • fcntl-变参函数
        • 复制文件描述符-dup
        • 修改文件属性-open的时候对应flag属性
      • 设置方法
//获取原来的flags
int flags = fcntl(fd[0],F+GETFL);
//设置新的flags
flag |=O_NONBLOCK;
fcntl(fd[0],F_SETFL,flags)fcntl(fd[0],F_SETFL,flags);
2.7.查看管道缓冲区大小
  • 命令

    • ulimit -a
  • fpathconf

父子进程通过管道通信

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

int main()
{
        pid_t pid;
        int fd[2];
        if(pipe(fd))
        {
                printf("create pipe failed\n");
                return -1;
        }
        printf("create pipe successed\n");
        pid = fork();
        if(pid == -1)
        {
                printf("create process failed\n");
                return -2;
        }
        else if(pid > 0)
        {
                close(fd[0]);
                dup2(fd[1],STDOUT_FILENO);//将管道的写端重定义从终端写入
                execlp("ps","ps","aux",NULL);//让父进程执行ps aux 的命令并把数据写到管道
        }
        else if(pid == 0)
        {
                close(fd[1]);
                dup2(fd[0],STDIN_FILENO);//将管道的读出重定义为读到终端
                execlp("grep","grep","bash",NULL);//子进程执行grep bash命令筛选父进程写入的数据并显示到终端
        }

        return 0;
}

3.有名管道

//函数形式:
int mkfifo(const char \*filename,mode_t mode);
/*
*function:创建管道文件
*param:管道文件文件名,权限,创建的文件权限仍然和umask有关系。
*return:创建成功返回0,创建失败返回-1。
*/
3.1.特点
  • 有名管道

  • 在磁盘上有这样一个文件 ls -l ->p

  • 也是一个伪文件,在磁盘大小永久为0

  • 数据存在内核中有一个对应的缓冲区

  • 半双工通信方式

3.2.使用场景

没有血缘关系的进程间通信

3.3.创建方式
  • 命令:mkfifo 管道名

  • 函数:mkfifo

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>


int main()
{
        int ret;
        ret = mkfifo("./myfifo",0777);
        if(ret == -1)
        {
                printf("create myfifo failed\n");
                return -1;
        }


        return 0;
}

在这里插入图片描述

3.4.fifo文件可以使用io函数进程操作
  • open/close

  • read/write

  • 不能执行lseek操作

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

int main()
{
	int ret;
	int fd;
	char ReadBuf[50] = {0};
	ret = mkfifo("./myfifo",0777);//创建有名管道
	if(ret == -1)
	{
		printf("make fifo failed\n");
		return -1;
	}

	fd = open("./myfifo",O_RDONLY);//打开有名管道
	if(fd == -1)
	{
		printf("open file failed\n");
		return -1;
	}
	ret = read(fd,ReadBuf,50);//读有名管道的内容
	printf("read %d byte is %s",ret,ReadBuf);

	close(fd);
	return 0;
}

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

int main()
{
	int ret;
	int fd;
	char *str = "hello world";//预定要发送的内容也可以设置从控制终端读
	fd = open("./myfifo",O_WRONLY);
	if(fd == -1)
	{
		printf("open file failed\n");
		return -1;
	}
	ret = write(fd,str,strlen(str));//写数据
	if(ret == -1)
	{
		printf("write error\n");
		return -1;
	}
	close(fd);
	return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值