当前位置: 首页 > news >正文

进程间通信-IPC机制

原因:进程间空间独立,无法直接通信,需要IPC机制实现通信

同一主机进程间通信:

1、古老的通信方式

        无名管道:可以用于同一主机,任意进程间通信

        有名管道:只能用于同一主机,具有亲缘关系的进程间通信(父子进程间)

        信号:进程间通知机制

2、IPC对象通信system V

        共享内存:效率最高

        消息队列:

        信号量集(信号灯)

主要同在不同主机进程间通信

1、socket通信

        网络通信

1.无名管道

只能用于同一主机,具有亲缘关系的进程间通信(父子进程间)

无名管道操作流程:

1.创建无名管道:pipe()        pipefd[0] 读端         pipefd[1]:写端

                #include <unistd.h>

               int pipe(int pipefd[2]);

2.写管道:write

3.读管道:read

4.关闭管道:close

管道本质:

内核空间中的一段缓冲区,遵循先进先出的特点

无名管道的:读写段不能交换

无名管道默认大小:65536bytes = 64k

管道的特性:

1.写阻塞:读端和写端都存在,向管道写数据,当管道满时,发生写阻塞

2.度阻塞:读端和写端都存在,从管道中读数据,若管道为空,则发生读阻塞

3.读返回0:若写端关闭,从管道中读取数据,若管道中有数据,则读到数据,若管道中没有数据,read则返回0,不在阻塞

4.管道破裂:读端关闭,向管道中写入数据,发生管道破裂

2.有名管道

1)有名管道本质:
内核空间的一段缓冲区,但这块缓冲区和一个管道文件相关联。

2)有名管道的操作流程:

1. 创建管道文件 mkfifo、mkfifo();
2. 打开管道文件 open();
3. 写管道文件 write();
4. 读管道文件 read();
5. 关闭管道文件 close();
6. 删除管道文件 int remove(const char *pathname);

        int mkfifo(const char *pathname, mode_t mode);
功能:创建一个管道文件
参数:
pathname:管道文件的名称
mode:管道文件的读写执行权限
返回值:
成功:0;
失败:-1

3.信号

信号:实现进程间的通知机制、实现进程间的异步通信、软中断

异步通信:接受方不知道什么时候发送方会发送数据。

1.系统支持的信号

查询系统支持的信号指令:kill-1

系统支持的信号:

 1) SIGHUP     2) SIGINT     3) SIGQUIT     4) SIGILL     5) SIGTRAP
6) SIGABRT     7) SIGBUS     8) SIGFPE     9) SIGKILL    10) SIGUSR1
11) SIGSEGV    12) SIGUSR2    13) SIGPIPE    14) SIGALRM    15) SIGTERM
16) SIGSTKFLT    17) SIGCHLD    18) SIGCONT    19) SIGSTOP    20) SIGTSTP
21) SIGTTIN    22) SIGTTOU    23) SIGURG    24) SIGXCPU    25) SIGXFSZ
26) SIGVTALRM    27) SIGPROF    28) SIGWINCH    29) SIGIO    30) SIGPWR
31) SIGSYS    34) SIGRTMIN    35) SIGRTMIN+1    36) SIGRTMIN+2    37) SIGRTMIN+3
38) SIGRTMIN+4    39) SIGRTMIN+5    40) SIGRTMIN+6    41) SIGRTMIN+7    42) SIGRTMIN+8
43) SIGRTMIN+9    44) SIGRTMIN+10    45) SIGRTMIN+11    46) SIGRTMIN+12    47) SIGRTMIN+13
48) SIGRTMIN+14    49) SIGRTMIN+15    50) SIGRTMAX-14    51) SIGRTMAX-13    52) SIGRTMAX-12
53) SIGRTMAX-11    54) SIGRTMAX-10    55) SIGRTMAX-9    56) SIGRTMAX-8    57) SIGRTMAX-7
58) SIGRTMAX-6    59) SIGRTMAX-5    60) SIGRTMAX-4    61) SIGRTMAX-3    62) SIGRTMAX-2
63) SIGRTMAX-1    64) SIGRTMAX

常用信号

2)SIGINT:CRTL + C        让一个进程打断

3)SIGQUIT:CRTL + \        让一个进程结束

9)SIGKILL        强制让一个进程结束

11)SIGSEGV         让一个进程结束(段错误)

13)SIGPIPE        让一个进程结束(管道破裂)

14)SIGALRM        让一个进程结束(定时时间到达)

17)SIGCHLD        子进程结束发送给父进程

18) SIGCONT        让停止态的进程继续执行

19)SIGSTOP        让运行态的进程进入停止态(暂停)强制停止

20)  SIGTSTP        crtl + z 让进程进入暂停态,后台进程来自终端的停止信号

10)SIGUSR1

12)SIGUSR2            用户自定义的信号

9)SIGKILL

19)SIGSTOP        管理员信号:只能按照默认方式处理,不能够被忽略和捕获

2.信号处理流程

当进程收到一个信号,会打断该进程正在执行的任务,处理信号产生的事件;当该处理事件处理完时,进程又从原来的位置继续执行

signal: 注册一个信号

#include <signal.h>

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

功能:设置信号的处理方式(注册一个信号)

参数:

        signum:要处理的信号的编号

        handler:

                        SIG_IGN:以许略的方式处理该信号(不处理)

                        SIG_DFL:以缺省方式处理(系统默认处理)

                        函数的地址:以捕获方式处理(自定义)

返回值:

        失败:NULL

        成功:返回自定义的函数入口

void(*sighandler_t)(int signum);

sighandler_t:执行信号任务处理函数的入口

参数:

        signum:触发该任务函数的信号

注意:

        1.若信号不被注册,则按照默认方式处理

        2.信号只需要注册一次

        3.每次信号的到来都会触发一次信号任务处理函数;

        4.信号尽可能早注册

3.发送信号

1.kill命令

2.kill()

int kill (pid_t pid, int sig)

功能:给指定的进程发送一个信号

参数:

        pid:接收信号的进程PID

        sig:信号的编号

返回值:

        成功:0

        失败:-1

3)子进程结束时,会发送SIGCHLD信号给父进程

        子进程空间异步回收:通过子进程发送的SIGCHLD信号实现

4)int raise(int sig)

给自己所在进程发送信号

5)unsigned int alarm(unsigned int seconds)

功能:设置一个闹钟,当闹钟时间到达时,向自己所在进程发送一个SIGALRM信号

参数:

        seconds:设置的闹钟定时时间

返回值:

        成功:返回上次设定剩余的时间

        上次未设定返回0

6)pause()

功能:让一个进程挂起(进入到睡眠状态)

注意:

        1.pause可以被一个信号唤醒

        2.这个信号必须要被捕获

4.共享内存

共享内存:进程间效率最高的通信模式

(1)通信原理

使用内核空间中的内存区域共享数据

使用内存映射技术,减少的数据的反复拷贝,提高了通信效率。

虚拟内存空间会通过mmu内存管理单元映射到实际内存空间,将共享内存控价和虚拟内存空间通过MMU映射到同一块实际的物理内存空间,从而导致数据共享

(2)共享内存操作流程

IPC对象

1)创建一个IPC key:

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

功能:创建一个IPC key

参数:

        pathname:路径

        proj_id:工程ID

        注意:两个进程创建key时,必须传递相同的参数

返回值:

        成功:IPCkey

        失败:-1

 2 ) 创建内存共享:

int shmget(key_t key, size_t size, int shmflg);   

功能:创建一个共享内存

参数:

        key:IPC key

        size:共享内存的大小

                会被扩展成PAGE_SIZE(4096bytes)的整数倍

        shmflg:

                IPC_CREAT | 0664       

返回值:

        成功:共享内存的ID

        失败:-1

3)建立共享内存段和用户空间的内存映射:

void *shmat(int shmid, const void *shmaddr, int shmflg);      

功能:建立共享内存内存映射

参数:

        shmid:共享内存id

        shmaddr:映射用户空间首地址

                NULL:让系统分配

        shmflg:

                SHM_RDONLY:只读

                !SHM_RDONLY:可读可写

返回值:

        成功:映射的用户空间首地址

        失败:void(*) -1

4)向共享内存写入数据-->通过用户空间首地址

5)解除映射关系

int shmdt(const void *shmaddr);

功能:解除内存映射关系

参数:

        shmaddr:要解除内存映射的首地址

返回值:

        成功:0

        失败:-1


6)删除共享内存

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

功能:操作共享内存

参数:

        shmid:要操作的共享内存id

        cmd: 要执行的操作指令

                IPC_RMID:删除操作

        buf:设置的参数

返回值:

        成功:0

        失败:-1

ipcs-a 查看内核中的IPC对象

ipcrm-s 删除信号量集

ipcrm-m 删除共享内存

ipcrm-m shmid

ipcrm-M shmkey

例如进程sent 发送一个hello,进程recv收到hello

#include "head.h"int main(int argc, const char *argv[])
{//ftok();//shmget();//shmat();//p-->//shmdt();//shmctl();key_t key = ftok(".", '!');if (key < 0){perror("ftok error");return -1;}printf("key = %x\n", key);int shmid = shmget(key, 4096,IPC_CREAT|0664);if (shmid < 0){perror("shmget error");return -1;}printf("shmid = %d\n", shmid);void *pmem = shmat(shmid, NULL, !SHM_RDONLY);if ((void *)-1 == pmem){perror("shmat error");return -1;}//*((int *)pmem) = 10;strcpy((char *)pmem, "hello");shmdt(pmem);//shmctl(shmid, IPC_RMID, NULL);return 0;
}
#include "head.h"int main(int argc, const char *argv[])
{//ftok();//shmget();//shmat();//p-->//shmdt();//shmctl();key_t key = ftok(".", '!');if (key < 0){perror("ftok error");return -1;}printf("key = %x\n", key);int shmid = shmget(key, 4096, IPC_CREAT|0664);if (shmid < 0){perror("shmget error");return -1;}printf("shmid = %d\n", shmid);void *pmem = shmat(shmid, NULL, !SHM_RDONLY);if ((void *)-1 == pmem){perror("shmat error");return -1;}printf("recv: %s\n", (char *)pmem);	shmdt(pmem);//shmctl(shmid, IPC_RMID, NULL);return 0;
}

5.信号量集

实现进程间同步

6.消息队列

和管道类似,有同步效果

增加了数据的等级(优先级:优先级数据越小,优先级越高)

http://www.dtcms.com/a/343862.html

相关文章:

  • 【开发日记】SpringBoot 实现支持多个微信小程序的登录
  • 初始数据结构——反射、枚举与Lambda的奇幻冒险
  • 如何理解AP服务发现协议中“如果某项服务需要在多个网络接口上提供,则应为每个网络接口使用一个独立的服务器服务实例。”?
  • 《Linux 网络编程一:网络编程导论及UDP 服务器的创建与数据接收》
  • “我 / 店模式” 靠联盟 + 积分破局,实现三方共赢!
  • 【Oracle】内存管理实战指南:ASMM vs AMM 配置全解析
  • Rust Web开发指南 第一章
  • 服务发现实例和服务实例是不同的
  • 血管介入医疗AI发展最新方向与编程变革:从外周、神经到冠脉的全面解析
  • RabbitMQ面试精讲 Day 27:常见故障排查与分析
  • yggjs_rlayout使用教程 v0.1.0
  • Linux系统之Ubuntu安装cockpit管理工具
  • Jenkins发布spring项目踩坑——nohup java -jar发布后显示成功,但实际jps查询并未运行
  • React 学习笔记1 组件、State
  • 【Tech Arch】Hadoop YARN 大数据集群的 “资源管家”
  • 企业级知识库+智能客服地大模型对比表
  • 实现自己的AI视频监控系统-第一章-视频拉流与解码4(重点)
  • MATLAB启动路径MATLAB202X/bin更改问题
  • 【Python】-- 机器学习项目 - 基于逻辑回归算法的乳腺癌数据集分类
  • 理解AI 智能体:智能体架构
  • DAY14-新世纪DL(DeepLearning/深度学习)战士:破(优化算法)2
  • k8sday14数据存储(2/2)
  • BigData大数据应用开发学习笔记(03)离线处理--数据仓库Hive
  • 直播预约 | CATIA MODSIM SmartCAE带练营第3期:让每轮设计迭代都快人一步!
  • 【C语言16天强化训练】从基础入门到进阶:Day 6
  • 前端查漏补缺
  • 图表组件SciChart WPF再升级:v8.9带来油气井图、新交互与可视化增强
  • PDF文档安全升级:三招实现文本转曲线(防篡改+高清输出)
  • WPF控件随窗体大宽度高度改变而改变
  • Spring Boot 集成 Swagger UI 详细教程