IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> IPC(进程间通信) -> 正文阅读

[系统运维]IPC(进程间通信)

IPC(进程间通信)

进程是操作系统分配资源的基本单位,也就是说进程间的资源是独立的。一个进程无法直接访问另一个进程的资源。

但是进程并不是孤立存在的,进程间需要进行数据传输、进程控制、通知事件、资源共享,所以进程间需要通信。

进程的用户空间对于每个进程而言是独立的,所有内核空间都是共享的。进程的内核空间是所有进程共享的。其实是mmu映射的物理内存属于同一块。所以进程间通信其实是在内核中创建一块缓冲区,将用户空间中的数据拷贝到该缓冲区实现进程间通信的。

?/*
内核空间:
?? ?内核空间的线地址是所以进程共享的,但是只有在内核态的进程才能共享。用户进程可以通过系统调用切换到内核态?? ?
*/

进程间通信方式

同一个主机:

匿名管道(只能在有血缘关系的进程间通信)

有名管道

内存映射

内存共享

消息队列

信号量

socket本地套接字

不同主机间:

socket套接字

管道

匿名管道
    匿名管道也成管道。管道实质上是一个在内核缓冲区中的开辟的缓冲区,管道的存储能力有限(Linux下默认情况下4K)。
管道具有文件的特性,可以像操作文件那样操作管道。管道的数据传输是字节流、通过管道的数据顺序的、半双工、一次性  操作。其实现是一个循环队列。
    匿名管道没有文件实体,有名管道有文件实体,但是不存储东西,只是用来不同进程间能够通过文件找到彼此。匿名管道只能用于具有血缘关系的进程间,因为父子进程件的文件描述符是一样的。
int pipe(int pipefd[2]); ? //创建匿名管道
    pipfd[0]:读端
 ? ? pipefd[1]:写端
 ? ? ? ?
long fpathconf(int fd,int name);//参看管道缓冲区大小
    eg:fpathconf(pipefd[0],_PC_PIPE_BUF);
?
?
//使用一个匿名管道的流程
1.父进程创建一个管道
2.fork()
3.父进程关闭读端 ?close(pipefd[0]);
4.子进程关闭写端 ?close(pipefd[1]);
有名管道
    由于匿名管道没有名字,只能用于亲缘关系的进程间通信。为了客服这个缺点,提出了有名管道(FIFO)
    有名管道不同于匿名管道之处在于它提供了一个路径名,以FIFO的文件形式存在文件系统,并且使用起来于普通文件一样。一个进程可以通过访问FIFO文件的路径,就能去于另一个没有血源关系的管道通信。
    FIFO在文件系统中作为一个特殊的文件存在,但是FIFO不存东西,内容存在内存中。当使用FIFO的进程退出后,FIFO将以文件的方式保存在文件系统中。FIFO因为有名字,不相干的进行可以通过打开有名管道进行通信。
int mkfifo(const char*pathnaem,mode_t mode);
//使用注意事项
/*
    1.一个为只读而打开的有名管道会阻塞,直到另一个进程为只写打开该有名管道
    2.一个为只写而打开的有名管道会阻塞,直到另一个管道为只读打开该有名管道
*/

管道的读写行为

1.读管道

1).管道中有数据:read返回实际读到的字节数

2).管道中无数据:

(1).管道写端关闭:read返回0 有客户端退出....

(2).写端没有全部关闭:read阻塞,如果设置成非阻塞,通过返回值判断

2.写管道

1).管道读端关闭,进程终止(发送SIGFIFE信号 默认执行终止进程)

向一个读端关闭的管道写数据

2).读端没有全部关闭

(1).管道已满,write阻塞

(2).管道未满,write将数据写入,返回实际写入的字节数

内存映射(非阻塞的)

内存映射(Menrmory-mapped I/O)是将磁盘文件中的数据映射到内存,用户通过修改内存就能够修改磁盘文件。

/* ? mmap函数 ? ?*/

//在内存中建立内存映射区
void *mmap(void* adrr,size_t length,int port,int flags,int fd,off_t offset);
返回值:成功返回内存映射区的首地址,失败返回-1(宏MAP_FAILED)
参数:
? ? adrr:?? ?建立的映射区的首地址,由Linux内核指定。传NULL
? ? length:?? ?欲创建映射区的大小(由磁盘文件大小确定)--->分页的整数倍
?? ?prot: ? 映射区的权限 ?PORT_READ ? PROT_WRITE ? PROT_READ|PROT_WRITE
? ? flags: ?参数标志位 ? ?
? ? ? ? ?? ?MAP_SHARED:将映射区的操作同步到磁盘文件
? ? ? ? ? ? MAP_PRIVATE:不将映射区的操作同步到磁盘文件
? ? fd:?? ? ? ?用来建立映射区的文件描述符
? ? offset: ?映射区文件的偏移量(4K整数倍) ? 文件大小不能为0
? ? ? ??
//释放建立的内存映射区
int munmap(void *adrr,size_t length); ?//adrr一定要内存映射区的首地址

匿名映射

映射区来完成文件读写操作十分方便,父子进程间通信有很方便。但是每次建立映射区都要依赖一个文件。

通过建立匿名映射可以不通过文件就可以实现父子进程间通信。

Linux中指定将第三个参数:flags设定为 MAP_SHARED | MAP_ANONYMOUS

int *adrr = mmap(NULL,4,PORT_READ|PORT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);

内存映射区实现进程间通信的过程

?

有关系的进程(父子进程)
    -在fork()之前通过唯一的父进程,先创建内存映射区(可以建立匿名映射区)
    -创建成功后,fork()创建子进程
    -父子进程共享创建的内存映射区(fork()之后就可以通信了)
无关系的进程
	-准备一个大小不是0的磁盘文件
	-进程1:通过磁盘文件建立内存映射区,得到一个映射区首地址
	-进程2:通过磁盘文件建立内存映射区,得到一个映射区首地址
	-使用内存映射区进行通信

?

信号

信号是一种信息的载体,是一种重要的通信方式。信息具有简单、不能携带大量信息、满足某种条件才能发送、优先级比较高(软中断)。信号是由内核负责发送、内核处理。信号具有延时性。

//信号相关事件和状态
引发内核产生信号的事件:
	1.对于前台进程,用户在终端输入特殊字符  ctrl+c  ctrl+/
    2.硬件异常 eg:非法访问内存(段错误)  除0  内存对齐出错(总线错误)
    3.进程状态的改变  eg:子进程退出给父进程发送 SIGCHLD
    4.运行相关的命令/函数
递达:
    信号递送并到达进程
未决:
    信号产生到被处理的这段时间
阻塞:
    阻塞信号被处理,而不是阻止信号产生。让系统暂时保留信号待以后发送。
信号处理方式:
    执行默认动作
    忽略
    捕捉(回调用户的捕捉函数)

?

Linux内核中的进程控制块PCB包含了与信号相关的信息,主要是未决信号集和阻塞信号集。内核使用位图机制来实现的,但是操作系统不允许我们直接对这两个信号集直接位操作。需自定义另一个信号集,借助该信号集来影响阻塞信号集,阻塞信号集影响未决信号集。

阻塞信号集:将某些信号加入阻塞信号集后,该信号的位置被设置为1,设为屏蔽。当屏蔽之后,再收到该信号,该信号 的处理将推后(解除屏蔽后)。

未决信号集:当信号产生,未决信号集中描述该信号的位翻转为1,表示该信号处于为决状态。当信号被处理翻转回0。

从内核产生信号后由于某些原因不能到达(阻塞)。这类信号的集合称为未决信号集。在屏蔽解除之前一直 处于未决状态。

信号编号

常规信号:1~31号

实施信号:31~63号

信号的四要素:

1.编号 2.名称 3.事件 4.默认处理动作

//我们在使用信号的时候,尽量使用名称。一些信号可能有三个值,在不同的操作系统中使用的值不一样,LINUX使用中间值
/*
	默认执行动作:
		Term:终止进程
		lgn:忽略信号
		Core:终止进程,产生Core文件(通过Core可以查看进程死亡的原因,用于GDB调试)
		Stop:停止(暂停)进程
		Cont:继续运行进程
*/

//9)SIGKILL    19).SIGSTOP信号 不能被忽略和捕捉,只能执行默认动作(终止进程)。甚至不能设置阻塞。

?

常用信号

 2)SIGINT:当用户按下ctrl+c ?用户终端向正在运行中的由该终端启动的程序发出此信号。默认动作为终止进程
 3)SIGQUIT:当用户按下ctrl+\ 用户终端向正在运行中的由该终端启动的进程发送该信号。默认动作终止进程
 9)SIGKILL:无条件终止信号 ? 不能捕捉、不能忽略、不能设置为阻塞
11)SIGPIPE:向一个没有读端的管道写数据。默认动作为终止进程
17)SIGCHLD:子进程结束时,父进程回收到这个信号。默认动作忽略这个信号,通过SIGCHLD可以实现对子进程的回收
18)SIGCONT:如果进程终止,则使其继续执行
19)SIGSTOP:终止进程 ? ? ? ? 不能捕捉、不能忽略、不能设置为阻塞

信号产生函数

int kill(pid_t pid,int sig);//向指定进程pid发送信号sig    -pid ? ? ? ?>0 ? 将信号发送给指定的进程 ? ? ? ?-1 ? 将信号发送给每一个有权限接受这个信号的进程 ? ? ? ?0 ? ?将信号发送给当前进程组 ? ? ? ?<-1 ?|pid|发送给指定的进程组 ? ?-sig ? ? ? ?发送的信号 int raise(int sig); //给当前进程发送信号?int abort(void); ? ?//给当前进程发送 SIGABRT  杀死当前进程,并产生core文件

设置定时器

信号集操作函数

?

信号捕捉

信号的产生和捕捉都是内核完成的

?

内核实现信号捕捉过程:

?

内存共享

共享内存允许两个或多个进程共享物理内存同一块区域(通常被称为段)。由于共享内存段会成为一个进程用户空间的一部分,因此这种PIC机制无需内核介入。所需要做的就是让一个进程将数据复制进共享内存中,并且这部分数据会对其它所有共享同一个段的进程可用。

?

?

对比:

管道对比-->管道是在内核区建立一个缓冲区,发送方需要将待发送的数据先拷贝到内核缓冲区;接受进程,需 要从内核缓冲区将数据拷到用户区。

内存映射-->内存映射是建立一个内存映射区与文件相关联,通过这个共享这个文件为媒介实现进程间通信。文 件是保存在磁盘上的,速度相对较慢。

内存共享-->直接共享一个物理内存段,不需要内核介入,只需要将数据拷贝到内存共享段中,就可以被其他共 享这段物理内存段的进程共享,实现进程间通信。在内存上时间读取,速度相对较快。

共享内存操作API

?

共享内存操作命令

?

?

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-04-09 18:57:31  更:2022-04-09 19:01:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 23:04:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码