Linux进程间通信

目录

1. 匿名管道

2. 命名管道

3.命令行中的管道("|")

4. 进程间通信 IPC

5. 共享内存

5.1 共享内存的创建

5.2 共享内存的释放

5.2 共享内存的关联和去关联

1. 共享内存的关联(shm attach)

2. 共享内存的去关联(shm deatch)

6. 消息队列

6.1 消息队列的创建

6.2 消息队列的释放

 6.2 消息队列发送数据

 6.2 消息队列获取数据


1. 匿名管道

管道

  • 从一个进程连接到另一个进程的数据流称为一个“管道”。
  • 管道的生命周期是随进程结束而结束的
  • 管道是自带同步与互斥机制的

比如在shell终端执行命令: ps -a | grep -Ei  "test"

这个操作就是把ps -a的输出(stdout)通过管道输入(stdin)到可执行程序grep 

  • 我们将一次只允许一个进程使用的资源,称为临界资源

匿名管道:是一种特殊的管道,仅限于本地父子进程之间的通信

  • pipe函数:创建匿名管道

int pipe(int pipefd[2]);

pipe函数调用成功时返回0,调用失败时返回-1。

pipefd[0] : 管道的读fd 

pipefd[1]:管道的写fd

  • 匿名管道使用步骤:

1.使用pipe()函数创建管道(可读写)

2.使用fork()函数创建子进程(父子进程均可对管道读写)

3.父进程关闭写fd(fd[1]), 子进程关闭读fd(fd[0]), 保证达到如下效果

在这里插入图片描述

 注意:

  1. 管道只能够单向通信,因此当父进程创建完子进程后,需要确认父子进程谁读谁写,然后关闭相应的读写端。
  2. 管道写端写入的数据会被内核缓冲,直到从管道的读端被读取。
  3. 管道是半双工通信的。
  4. 如果需要实现全双工通信,需要进程建立两根管道

在这里插入图片描述

 5.管道的容量可通过ultimate -a进行设置,查看

2. 命名管道

匿名管道只能用于相关的进程之间的通信,要让两个无关的进程通信,需要用到命名管道。

命名管道就是一种特殊类型的文件。

  • 创建命名管道
[cl@VM-0-15-centos fifo]$ mkfifo fifo

可在mkfifo的目录下查看到当前目录多了个fifo文件

如下例子;一个进程写到fifo文件(echo "hello" > fifo),一个进程从fifo文件去读(cat < fifo)

在这里插入图片描述

  •  函数创建fifo
int mkfifo(const char *pathname, mode_t mode);

第一个参数是pathname,表示要创建的命名管道文件。

mkfifo函数的第二个参数是mode,表示创建命名管道文件的默认权限。(创建出来文件的权限为:mode&(~umask))

  • 项目中用到的主要是用于,代码逻辑自测,用通过echo指令向一个fifo写入一些命令来测试某些函数。
  • 将fifo创建,读取的函数写在一个线程里面,让程序一直去读去终端echo输入的命令。

3.命令行中的管道("|")

管道(“|”)连接起来的各个进程是有亲缘关系的,它们之间互为兄弟进程。

使用命令行的位置并不存在fifo文件,所以:命令行对应的是匿名管道!!

4. 进程间通信 IPC

system V IPC是操作系统特地设计的一种通信方式。system V IPC提供的通信方式有以下三种:

system V共享内存:线程或进程之间消息交互
system V消息队列:线程或进程之间消息交互
system V信号量:同步与互斥

5. 共享内存

  • 基本概念

让不同的进程看到同一份物理内存,这块物理内存就叫做共享内存。

当申请了一块共享内存后,为了让各个进程看到同一个共享内存,因此每个共享内存被申请的时候都有一个key值,用于标识唯一性。

  • 命令:ipcs -q/ ipcs -m /ipcs -s列出消息队列/共享内存/信号量相关信息
  • 进程结束了,共享内存依旧存在
  • 5.1 共享内存的创建

1.在物理内存中申请共享内存空间

2.将申请到的共享内存挂接到地址空间,建立映射关系

  • 5.2 共享内存的释放

1.将共享内存与地址空间去关联,取消映射关系。

2.释放共享内存空间,将物理内存还给系统。

  • 可在C++的构造函数ftok(); shmget()的方式赋值到类的私有指针,在析构函数去shmdetach()

5.1 共享内存的创建

  • 共享内存的建立

1.在物理内存中申请共享内存空间

int shmget(key_t key, size_t size, int shmflg);
  • key: 共享内存在系统中的唯一标识符(传入的key参数是通过:ftok()函数的返回值决定的
  • size:待创建的共享内存大小
  • shmflg:创建共享内存的方式

调用成功:返回一个有效的fd,  失败返回-1.

key_t ftok(const char *pathname, int proj_id);

将一个已存在的路径名pathname和一个整数标识符proj_id转换成一个key值,称为IPC键值

  • pathname:路径名
  • proj_id:有如下两种参数,决定创建共享内存的方式。 

(1)使用组合IPC_CREAT,如果内核中不存在键值与key相等的共享内存,则新建一个共享内存并返回该共享内存的句柄;如果存在这样的共享内存,则直接返回该共享内存的句柄

  • 适用:每个进程都去调用ftok()和shmget(),这样可以保证不会重复创建。

(2)如果内核中不存在键值与key相等的共享内存,则新建一个共享内存并返回该共享内存的句柄;如果存在这样的共享内存,则出错返回

2.将申请到的共享内存挂接到地址空间,建立映射关系

5.2 共享内存的释放

  • 共享内存的释放

(1)可以通过ipcrm -m shmid命令释放指定sharememory id的共享内存资源。

(2)控制共享内存可用shmctl函数

int shmctl(int shmid, int cmd, struct shmid_ds *buf);
  • shmid: 共享内存的id
  • cmd:需要对shm执行的动作

cmd传入的常用的选项有以下三个:

选项作用
IPC_STAT获取共享内存的当前关联值,此时参数buf作为输出型参数
IPC_SET在进程有足够权限的前提下,将共享内存的当前关联值设置为buf所指的数据结构中的值
IPC_RMID删除共享内存段
  • buf:设置或获取所控制的共享内存的数据结构

函数返回0代表调用成功,返回-1代表调用失败。

5.2 共享内存的关联和去关联

  • 共享内存并没有提供任何的保护机制,包括同步与互斥。
  • 共享内存的attach和deattach针对的是进程和共享内存两者之间!!
  • shmat()操作之后,能够让进程以操作地址的方式操作共享内存。好处嘛:当时是方便代码的移植。

1. 共享内存的关联(shm attach)

将共享内存连接到进程地址空间。

void *shmat(int shmid, const void *shmaddr, int shmflg);
  • shmid: sharedmemory id
  • shmaddr: 共享内存映射到进程地址空间的某一地址,通常设为NULL,让内核决定
  • shmflg: 一些属性

调用成功:返回共享内存映射到进程地址空间的起始地址。

调用失败:返回(void*) -1

注:需要shmget()的第二个参数需要增加0666的权限。

关联查看

ipcs -m可看到 mattch的参数变为1 

2. 共享内存的去关联(shm deatch)

int shmdt(const void *shmaddr);
  • 传入shmaddr; 这个是shmat()函数的返回值,

shmdt调用成功,返回0。

shmdt调用失败,返回-1。

  • 小结:当共享内存创建好后就不再需要调用系统接口进行通信
  • 两个进程之间都去读写shared memory, 可以通过在共享内存里写标志位,比如变量A:1标识可读,2标识可写。每次进程在读写共享内存之前都看下这个变量A。写个while循环直到这个标志位被改变。

6. 消息队列

  • 用于一个进程向另外一个进程发送数据块的方法!!
  • 消息队列的资源也必须自行删除,否则不会自动清除

6.1 消息队列的创建

int msgget(key_t key, int msgflg);
  • 第一个参数key, 通过ftok()函数生成,这个key作为msgget()的第一个参数。
  • msgflag: 一些标志位
  • 调用成功返回一个fd

6.2 消息队列的释放

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

 6.2 消息队列发送数据

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

 6.2 消息队列获取数据

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值