×

进程间通信 共享内存 get函数

进程间通信 共享内存(linux两个进程间共享内存通信都需要调用shmget函数么)

admin admin 发表于2024-09-10 17:34:22 浏览5 评论0

抢沙发发表评论

本篇文章给大家谈谈进程间通信 共享内存,以及linux两个进程间共享内存通信都需要调用shmget函数么对应的知识点,文章可能有点长,但是希望大家可以阅读完,增长自己的知识,最重要的是希望对各位有所帮助,可以解决了您的问题,不要忘了收藏本站喔。

本文目录

linux两个进程间共享内存通信都需要调用shmget函数么

两个进程都需要调用shmget函数,是根据key值来实现访问同一个共享内存的。函数原型:int shmget(key_t key, size_t size, int shmflg)由于是两个进程访问,最好是做两手准备:1,先创建,若创建成功,可以直接使用。2,若创建失败--此时,很可能另一个进程已经创建成功了,就不能再创建了。此时,就改为只是获取。示例代码如下:int mid = shmget(key, size, IPC_CREAT | 0660);if(mid 《 0){ mid = shmget(key, 0, 0);}

进程间通信 内存映射和共享内存的区别

  内存映射文件是利用虚拟内存把文件映射到进程的地址空间中去,在此之后进程操作文件,就像操作进程空间里的地址一样了,比如使用c语言的memcpy等内存操作的函数。这种方法能够很好的应用在需要频繁处理一个文件或者是一个大文件的场合,这种方式处理IO效率比普通IO效率要高  共享内存是内存映射文件的一种特殊情况,内存映射的是一块内存,而非磁盘上的文件。共享内存的主语是进程(Process),操作系统默认会给每一个进程分配一个内存空间,每一个进程只允许访问操作系统分配给它的哪一段内存,而不能访问其他进程的。而有时候需要在不同进程之间访问同一段内存,怎么办呢?操作系统给出了创建访问共享内存的API,需要共享内存的进程可以通过这一组定义好的API来访问多个进程之间共有的内存,各个进程访问这一段内存就像访问一个硬盘上的文件一样。而.Net 4.0中引入了System.IO. MemoryMappedFiles命名空间,这个命名空间的类对windows 共享内存相关API做了封装,使.Net程序员可以更方便的使用内存映射文件。

linux 进程间通信的几种方式

第一种:管道通信两个进程利用管道进行通信时,发送信息的进程称为写进程;接收信息的进程称为读进程。管道通信方式的中间介质就是文件,通常称这种文件为管道文件,它就像管道一样将一个写进程和一个读进程连接在一起,实现两个进程之间的通信。写进程通过写入端往管道文件中写入信息;读进程通过读出端从管道文件中读取信息。两个进程协调不断地进行写和读,便会构成双方通过管道传递信息的流水线。第二种:消息缓冲通信多个独立的进程之间可以通过消息缓冲机制来相互通信。这种通信的实现是以消息缓冲区为中间介质,通信双方的发送和接收操作均以消息为单位。在存储器中,消息缓冲区被组织成队列,通常称之为消息队列。消息队列一旦创建后即可由多进程共享,发送消息的进程可以在任意时刻发送任意个消息到指定的消息队列上,并检查是否有接收进程在等待它所发送的消息。若有则唤醒它,而接收消息的进程可以在需要消息的时候到指定的消息队列上获取消息,如果消息还没有到来,则转入睡眠等待状态。第三种:共享内存通信针对消息缓冲需要占用CPU进行消息复制的缺点,OS提供了一种进程间直接进行数据交换的通信方式。共享内存,顾名思义这种通信方式允许多个进程在外部通信协议或同步,互斥机制的支持下使用同一个内存段进行通信,它是一种最有效的数据通信方式,其特点是没有中间环节,直接将共享的内存页面通过附接映射到相互通信的进程各自的虚拟地址空间中,从而使多个进程可以直接访问同一个物理内存页面。

unix系统中,哪些可以用于进程间的通信

Socke、共享内存、消息队列、信号量都可以用于进程间的通信。

一、管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信。  

二、命名管道(named    pipe):命名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。命名管道在文件系统中有对应的文件名。命名管道通过命令mkfifo或系统调用mkfifo来创建。  

三、信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数)。  

四、消息(Message)队列:消息队列是消息的链接表,包括Posix消息队列system    V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺 。 

五、内存映射(mapped    memory):内存映射允许任何多个进程间通信,每一个使用该机制的进程通过把一个共享的文件映射到自己的进程地址空间来实现它。  

六、信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。

Linux进程通信实验(共享内存通信,接上篇)

***隐藏网址******隐藏网址*** 实验要求:编写sender和receiver程序,sender创建一个共享内存并等待用户输入,然后把输入通过共享内存发送给receiver并等待,receiver收到后把消息显示在屏幕上并用同样方式向sender发送一个over,然后两个程序结束运行。 这个实验的难点主要在于共享内存的创建和撤销(涉及到的步骤比较多,需要理解各步骤的功能),以及实现两个进程间的相互等待(使用信号量来实现,这里使用了有名信号量) 实验心得:学习理解了linux的共享内存机制以及POSIX信号量机制。 两个实验虽然加强了对linux一些机制的理解,但是感觉对linux的学习还不够,需要继续学习。

进程间通信 (IPC):忙等待的互斥方案

鉴于不支持LaTeX公式,有兴趣自己查吧,文字表述总是不如数学公式直观。

同上面的概念类似,两个或多个进程读写某些共享数据,而最后的结果取决于进程运行得精确时序(也就是这些进程不满足Bernstein条件),我们把这种情况称为 竞争条件 。解决竞争条件的方法是实现 互斥 ,即以某种手段确保当一个进程在使用一个共享变量或文件时,其他进程不能做同样的操作。

我们把对共享内存进行访问的程序片段称为 临界区 ,如果存在某些方案,使得两个进程不可能同时处于临界区中,就能够避免竞争条件。对于这些方案,需要满足一下4个条件

在单处理器系统中,最简单的方法就是使每个进程刚刚进入临界区后立即屏蔽所有中断,并在就要离开之前再打开中断。屏蔽中断后,时钟中断也会被屏蔽。CPU只有发生时钟中断或其他中断时才会进行进程切换,这样,在屏蔽中断之后CPU将不会被切换到其他进程。于是,一旦某个进程屏蔽中断之后,他就可以检查和修改共享内存,而不必担心其他进程介入。

某些计算机中,特别是那些设计为多处理器的计算机,都有以免一条指令:TSL RX, LOCK,称为测试并加锁(test and set lock),它将一个内存字lock读到寄存器RX中,然后再该内存地址上存一个非零值。读字和写字操作保证是不可分割的,即该指令结束之前其他处理器均不允许访问该内存字。执行TSL指令的CPU将锁住内存总线,以禁止其他CPU在本指令结束之前访问内存。 为了使用TSL指令,要使用一个共享变量lock来协调对共享内存的访问。当lock为0时,任何进程都可以使用TSL指令将其设置为1,并读写共享内存。当操作结束是,进程用一条普通的move指令将lock的值重新设置为0.

可以看出TSL也是一个忙等待方案:进程在进入临界区之前先调用enter_region,在锁空闲之前一直循环等待。

一个可替代TSL的指令是XCHG,它原子性地交换了两个位置的内容,例如,一个寄存器与一个存储器字。

TSL和XCHG指令的函数形式描述在《操作系统教程》第五版有写,此处不详细描述。

整型变量turn,初始值为0,用于记录轮到哪个进程进入临界区,并检查或更新共享内存。开始时,进程0检查turn,发现其值为0,于是进入临界区。进程也发现其值为0,所以在一个等待循环中不但测试turn,看其值何时变为1.连续测试一个变量直到某个值出现为止,称为 忙等待 。由于这种方式浪费CPU时间,所以通常应该避免。只有在有理由认为等待时间是非常短的情况下,才使用忙等待。用于忙等待的锁,称为 自旋锁

这个算法的确避免了所有的竞争条件,但违反了临界区条件3(临界区外运行得进程不得阻塞其他进程),所以不是一个很好的方案。

在使用共享变量之前,各个进程使用其进程号0或1作为参数来调用enter_region。该调用在使用时将使进程等待,直到能安全地进入临界区。在完成对共享变量的操作之后,进程将调用leave_region,表示操作已完成,若其他的进程希望进入临界区,则现在就可以进入。

一开始,没有任何进程进入临界区中,现在进程0调用enter_region。它通过设置其数组元素和将turn置0来标识它希望进入临界区。由于进程1并不想进入临界区,所以enter_region很快便返回。 如果进程1现在调用enter_region,进程1将在此处挂起直到interested变成FALSE,该事件只有在进程0调用leave_region退出临界区时才会发生。

现在考虑两个进程几乎同时调用enter_region情况。它们都将自己的进程号存入turn,但只有后被保存进去的进程号才有效,前一个因被重写而丢失。假设进程1是后存入的,则turn为1。当两个进程都运行到while语句时,进程0将循环0次进入临界区,则进程1则将不断地循环而不能进入临界区,直到进程0退出临界区为止。

进程和进程之间无法共享内存

无法共享内存。每个进程都有自己独立的虚拟地址空间,进程之间的内存是相互隔离的,因此无法共享内存。共享内存是一种高效的进程间通信方式,它允许多个进程访问同一块物理内存,在共享内存中,多个进程可以访问同一块内存区域,这样就可以实现进程间的数据共享。

操作系统之 进程间通信的方式有哪些

进程能够单独运行并且完成一些任务,但是也经常免不了和其他进程传输数据或互相通知消息,即需要进行通信,本文将简单介绍一些进程之间相互通信的技术--进程间通信(InterProcess Communication,IPC)。由于篇幅有限,本文不会对每一种进行详细介绍。 进程间通信常见方式如下: 管道 FIFO 消息队列 信号量 共享内存 UNXI域套接字 套接字(Socket) 管道是一种古老的IPC通信形式。它有两个特点: 半双工,即不能同时在两个方向上传输数据。有的系统可能支持全双工。 只能在父子进程间。经典的形式就是管道由父进程创建,进程fork子进程之后,就可以在父子进程之间使用了。 system()函数虽然也能够执行系统命令,但是无法获取执行状态码,而执行系统命令本质上就需要创建子进程来完成,因此利用管道可以很方便的获取子进程的输出内容。本文不详细展开。 FIFO也被称为命名管道,与管道不同的是,不相关的进程也能够进行数据交换。 而FIFO也常常有以下两个用途: 无需创建中间临时文件,复制输出流 多客户-服务进程应用中,通过FIFO作为汇聚点,传输客户进程和服务进程之间的数据 两个没有亲缘关系的进程可以通过FIFO进行通信。 消息队列可以认为是一个消息链表,存储在内核中,进程可以从中读写数据。与管道和FIFO不同,进程可以在没有另外一个进程等待读的情况下进行写。另外一方面,管道和FIFO一旦相关进程都关闭并退出后,里面的数据也就没有了,但是对于消息队列,一个进程往消息队列中写入数据后退出,另外一个进程仍然可以打开并读取消息。消息队列与后面介绍的UNIX域套接字相比,在速度上没有多少优势。 信号量是一个计数器,它主要用在多个进程需要对共享数据进行访问的时候。考虑这一的情况,不能同时有两个进程对同一数据进行访问,那么借助信号量就可以完成这样的事情。 它的主要流程如下: 检查控制该资源的信号量 如果信号量值大于0,则资源可用,并且将其减1,表示当前已被使用 如果信号量值为0,则进程休眠直至信号量值大于0 也就是说,它实际上是提供了一个不同进程或者进程的不同线程之间访问同步的手段。 共享内存允许多个进程共享一个给定的存储区,由于它们是共享一块内存数据,因此其速度非常快。但是需要另外提供手段来保证共享内存的同步访问,例如它可以用到前面所提到的信号量来实现访问同步。 UNIX域套接字和套接字很相似,但是它有更高的效率,因为它不需要执行协议处理,例如计算校验和,发送确认报文等等,它仅仅复制数据。 当然,它也只适用于同一台计算机上的进程间通信。 例如redis服务配置unixsocket启动后,通过redis-cli的-s参数就可以指定UNIX域套接字,连接到redis服务器。 它会比使用网络套接字的速度要快。 这个不用多说,它利用网络进行通信,与前面所提到的通信方式不同的是,它能用于不同计算机之间的不同进程间通信。 本文简单介绍了进程间通信的常见方式,其中对管道和命名管道我们使用了一个例子来简单说明,因为我们可能会经常见到它。对于FIFO,最后一个引用它的进程终止时,留在FIFO的数据也将会被删除,而对于消息队列却不是这样,它会一直留到被显示删除或者系统自举,另外消息队列于其他方式相比并没有特别的优势。而信号量实际上常用于共享数据的同步访问。共享内存在进程间传递数据非常高效,但是系统没有对访问进行同步,因此还需要另外实现数据的访问同步。套接字(socket)是应该目前应用最广泛的进程间通信方式。

OK,关于进程间通信 共享内存和linux两个进程间共享内存通信都需要调用shmget函数么的内容到此结束了,希望对大家有所帮助。