进程间通信管道和信号共74页
linux进程通信机制管道
linux进程通信机制管道LINU某进程通信之管道进程间通信(IPC)指的是至少两个进程间传送数据或者信号的一些技术和方法,进程是计算机系统分配资源的基本单位,每个进程都有自己的一部分独立的系统资源,彼此是隔离的。
为了能使不同的进程互相访问资源并进行协调工作,才有了进程之间的通信。
操作系统中进程间传递的信息量有多有少,因此根据进程通信时信息量大小的不同,可以将进程通信划分为两大类型,一种类型主要用于传递进程之间同步、互斥、终止、挂起等控制信息的传递,由于进程互斥与同步交换的信息量较少,并且每次通信传递的信息量固定且效率较低,因此称这两种通信方式为低级通信方式,主要方式有信号量。
另一种类型在进程间以较高的效率传送大量数据,被称为高级通信方式,主要方式有管道,共享内存和消息队列。
下面就管道通信进行论述。
管道是Linu某支持的最初Uni某IPC形式之一,当两个进程利用管道进行通信时,发送信息的进程称为写进程,接收信息的进程称为读进程。
管道通信方式的中间介质就是文件,通常称这种文件为管道文件.它就像管道一样将一个写进程和一个读进程连接在一起,实现两个进程之间的通信。
写进程通过写入端(发送端)往管道文件中写入信息,读进程通过读出端(接收端)从管道文件中读取信息。
管道具有如下特点:1)管道是半双工的,数据只能向一个方向流动,数据只能由写的一方向读得一方流动。
2)单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,成为管道文件,但它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中。
3)数据的读出和写入:管道建立时,通信两端的任务都是被固定了的,也就是说,一端只能用于读,而另一端只能用于写,写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。
管道提供了从一种进程向另一种进程传输数据的有效方法,但是,管道还是存在一些不足:(1)因为读数据的同时也将数据从管道移去,因此管道不能用来对多个接受者广播数据。
进程间通信之管道
进程间通信之管道1、介绍管道和有名管道是最早的进程间通信机制之⼀,管道可⽤于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许⽆亲缘关系进程间的通信。
2、特点管道:本质是⼀个伪⽂件(实为内核使⽤环形队列机制,借助内核缓冲区(4k)实现)。
有名管道:不同于管道,它提供⼀个路径名与之关联,以FIFO的⽂件形式存在于⽂件系统中。
这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信,因此,通过FIFO不相关的进程也能交换数据。
半双⼯的,数据只能向⼀个⽅向流动;需要双⽅通信时,需要建⽴起两个管道;由两个⽂件描述符引⽤,⼀个表⽰读端,⼀个表⽰写端;规定数据从管道的写端流⼊管道,从读端流出(写⼊的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据,不⽀持诸如lseek()等⽂件定位操作);数据⼀旦被读⾛,便不在管道中存在,不可反复读取。
3、管道的读写⾏为使⽤管道需要注意以下4种特殊情况(假设都是阻塞I/O操作,没有设置O_NONBLOCK标志):1. 如果所有指向管道写端的⽂件描述符都关闭了(管道写端引⽤计数为0),⽽仍然有进程从管道的读端读数据,那么管道中剩余的数据都被读取后,再次read会返回0,就像读到⽂件末尾⼀样。
2. 如果有指向管道写端的⽂件描述符没关闭(管道写端引⽤计数⼤于0),⽽持有管道写端的进程也没有向管道中写数据,这时有进程从管道读端读数据,那么管道中剩余的数据都被读取后,再次read会阻塞,直到管道中有数据可读了才读取数据并返回。
3. 如果所有指向管道读端的⽂件描述符都关闭了(管道读端引⽤计数为0),这时有进程向管道的写端write,那么该进程会收到信号SIGPIPE,通常会导致进程异常终⽌。
当然也可以对SIGPIPE信号实施捕捉,不终⽌进程。
具体⽅法信号章节详细介绍。
4. 如果有指向管道读端的⽂件描述符没关闭(管道读端引⽤计数⼤于0),⽽持有管道读端的进程也没有从管道中读数据,这时有进程向管道写端写数据,那么在管道被写满时再次write会阻塞,直到管道中有空位置了才写⼊数据并返回。
进程间通信详解
进程间通信详解⼀、管道管道,通常指⽆名管道,是 UNIX 系统IPC最古⽼的形式。
1、特点:1. 它是半双⼯的(即数据只能在⼀个⽅向上流动),具有固定的读端和写端。
2. 它只能⽤于具有亲缘关系的进程之间的通信(也是⽗⼦进程或者兄弟进程之间)。
3. 它可以看成是⼀种特殊的⽂件,对于它的读写也可以使⽤普通的read、write 等函数。
只存在于内存中。
⼆、FIFOFIFO,也称为命名管道,它是⼀种⽂件类型。
1、特点1. FIFO可以在⽆关的进程之间交换数据,与⽆名管道不同。
2. FIFO有路径名与之相关联,它以⼀种特殊设备⽂件形式存在于⽂件系统中。
三、消息队列消息队列,是消息的链接表,存放在内核中。
⼀个消息队列由⼀个标识符(即队列ID)来标识。
1、特点1. 消息队列是⾯向记录的,其中的消息具有特定的格式以及特定的优先级。
2. 消息队列独⽴于发送与接收进程。
进程终⽌时,消息队列及其内容并不会被删除。
3. 消息队列可以实现消息的随机查询,消息不⼀定要以先进先出的次序读取,也可以按消息的类型读取。
四、信号量信号量(semaphore)与已经介绍过的 IPC 结构不同,它是⼀个计数器。
信号量⽤于实现进程间的互斥与同步,⽽不是⽤于存储进程间通信数据。
1、特点1. 信号量⽤于进程间同步,若要在进程间传递数据需要结合共享内存。
2. 信号量基于操作系统的 PV 操作,程序对信号量的操作都是原⼦操作。
3. 每次对信号量的 PV 操作不仅限于对信号量值加 1 或减 1,⽽且可以加减任意正整数。
4. ⽀持信号量组五、共享内存共享内存(Shared Memory),指两个或多个进程共享⼀个给定的存储区。
1、特点1. 共享内存是最快的⼀种 IPC,因为进程是直接对内存进⾏存取。
2. 因为多个进程可以同时操作,所以需要进⾏同步。
3. 信号量+共享内存通常结合在⼀起使⽤,信号量⽤来同步对共享内存的访问。
六、socket这是⼀种更为⼀般得进程间通信机制,它可⽤于⽹络中不同机器之间的进程间通信,应⽤⾮常⼴泛。
操作系统实验报告(进程的管道及消息通信)
printf("\n Ihave wrote:%s",string); write(fd,string,45); string[0]+=1; } else { read(fd,buf,256); printf("\n The context by I have read is :!%s",buf); buf[0]='\0'; } } close(fd); } 运行结果:
char parent[]="A message to pipe'communication.\n";
main() {
int pid,chan1[2]; char buf[100]; pipe(chan1); pid=fork(); if(pid<0) {
printf("to create child error\n"); exit(1); } if(pid>0) { close(chan1[0]); printf("parent process sends a message to child.\n"); write(chan1[1],parent,sizeof(parent)); close(chan1[1]); printf("parent process waits the child to terminate\n"); wait(0); printf("parent process terminate\n"); } else { close(chan1[1]); read(chan1[0],buf,100); printf("The message read by child process from parent is :%s.\n",buf); close(chan1[0]); printf("child process terminates\n"); } } 运行结果:
操作系统实验报告进程的管道及消息通信
运行结果如下:结果分析:父进程首先被调用时,运行结果为:之后父进程阻塞等待子进程终止,当系统调度子进程运行时,输出如下的信息:之后父进程被唤醒,调度运行,输出如下结果后程序退出。
对于以上的结果:首先父进程使用pipe(chan1)系统调用打开一个无名管道,之后创建一个子进程。
子进程复制父进程的打开文件表。
为了正确通信,父进程关闭读通道close(chan1[0]),子进程关闭写通道close(chan1[1])。
父进程向管道写,子进程从管道读。
完成一次通信之后,父进程分别关闭自己的写/读通信,管道文件消失。
2.以命名行为参数的管道文件的示例。
(假设有一个可执行程序chcase,从标准输入设备读字符,将小写字母转化成大写字母并输出。
主程序使用popen创建管道,实现蒋某文本文件中的字幕转化成大写字母,其中的文本文件名作为参数传进来。
)编写的程序如下:运行结果是:结果分析:通过程序运行结果可知,先打开文本文件,如果文本打开失败,则执行exit(1),退出程序,如果文本通过函数开成功,则popen 创建一个可写管道,将命令行chcase的输入与管道的输入连接起来,然后向管道输入数据,此时命令行就可以通过管道接受文本文件的数据了,在从文件中读出数据时,独处的内容放在line[]数组中,fpin表示从刚打开的文件里读出。
之后要编写字母大小写转化函数,来实现小写字母转化成大写字母。
3.创建有名管道。
编写的程序如下:运行结果是:前台运行结果:后台运行结果:结果分析:此程序是把管道和命令联系起来,read( )的系统调用格式是read(fd,buf,n),参数定义是int read(fd,buf,n); int fd; char *buf; unsigned n;它的功能是从fd所指示的文件中读出n个字节的数据,并将它们送至由指针buf所指示的缓冲区中。
如该文件被加锁,等待,直到锁打开为止;write( )系统调用格式是read(fd,buf,n),它的功能是把n个字节的数据,参数定义同read( ),而父进程则从管道中读出来自两个进程的信息,显示在屏幕上。
进程通信
24
消息队列
使用消息队列实现一个服务进程为多个客户进程 服务
25
消息队列
• 在设计UNIX的多进程间通信时,必须仔细分析所 设计的进程通信机制会不会产生死锁问题。 • 在使用管道,消息队列,信号量时,都有可能产 生死锁。
26
消息队列
– 如果客户进程每次都要产生一个体积较大的请求消息 发送到消息队列。假设消息队列最多可以容纳8个这样 的消息,而有9个客户端进程。 – 在特定的情况下,9个进程同时把自己的请求消息发送 到消息队列,由于队列最多可以容纳8个消息,这样, 最后一个进程的发送请求被阻塞。 – 当服务进程从队列里取走一个数据正在进行处理的时 候,这第9个进程醒过来,把它的数据注入到消息队列 中,导致队列满。服务进程在处理完毕数据后,处理 结果要发送到消息队列中,队列满,就会等待; – 而所有的9个客户进程都在等待自己的应答消息,也在 等待。这样死锁就会产生。
参数key是信号量组的KEY。 参数nsems指明信号量组中包含有多少个信号量,这个 参数仅在创建新信号量组时使用,获取已存在的信号 量组,将这个参数设为0。
23
消息队列
• 消息队列的特点
– 保持了记录边界,而且消息传递是可靠的,不会丢失 数据。这对于应用程序来说非常方便; – 独立启动的多个进程只要使用相同的消息队列KEY值, 就可以共享消息队列; – 可以多路复用,实现了“信箱”的功能,便于多个进 程共享消息队列; – 同共享内存相比,消息队列也有缺点:多个进程之间 的通信数据必须经过内核复制,当数据量极大时,不 如共享内存快。
14
命名管道FIFO
• 命名管道的使用
一旦用mkfifo()创建了一个FIFO,就可以像一般的文件 一样对其进行I/O操作
08第08章 进程间通信-管道和信号
管道示例
2010-12-12
人民邮电出版社出版 杨宗德编著
3
Linux高级程序设计(第2版)
创建无名管道
2010-12-12
人民邮电出版社出版 杨宗德编著
4
Linux高级程序设计(第2版)
文件描述符重定向
• • • • • (1)cat<test01 (2)cat>test02<test01 (3)cat>test02 2>error <test01 (4)cat>test02 1&2 <test01 (5)cat 1&2 1>test02<test01
2010-12-12
人民邮电出版社出版 杨宗德编著
14
Linux高级程序设计(第2版)
管道基本特点总结
• • • • 两类型管道具有以下特点: (1)管道是特殊类型的文件,在满足先入先出的原则条件下可以进行读写,但 不能定位读写位置。 (2)管道是单向的,要实现双向,需要两个管道。无名管道只能实现亲缘关系 进程间通信(即无名管道的两个文件描述符可以被两者都访问到),而有名管 道以磁盘文件的方式存在,可以实现本机任意两进程间通信。 (3)无名管道阻塞问题。无名管道无须显式打开,创建时直接返回文件描述符, 而在读写时需要确实对方的存在,否则将退出。即如果当前进程向无名管道的 写数据时,必须确定其别一端为某个进程(这个进程可以是当前进程)拥有, 即有一个(或多个)进程的文件描述符表中至少有一个成员指向管道的另一端 (显然,能够读写管道当前端,则本端在当前进程中是可以访问的)。如果写 入无名管道的数据超过其最大值,写操作将阻塞,如果管道中没有数据,读操 作将阻塞,如果管道发现另一端断开(另一端文件描述符关闭),将自动退出。 (4)有名管道阻塞问题。有名管道在打开时需要确实对方的存在,否则将阻塞。 即以读方式打开某管道,该操作得以继续执行的条件是:在此之前,已经有一 个进程以写的方式打开此管道,否则阻塞,直到条件满足,因此有名管道将阻 塞在打开位置。也可以以读写(O_RDWR)方式打开有名管道,进程能够继 续执行(不阻塞),只是这样操作没有什么意思,即当前进程读,当前进程写。
进程和进程间通信
进程和进程间通信进程是操作系统中的一个基本概念,它代表了一个正在运行的程序实例。
在现代操作系统中,多个进程可以同时运行,并且需要进行相互之间的通信和协调。
进程间通信(Inter-Process Communication,IPC)是指不同进程之间进行数据交换和共享的机制。
一、进程间通信的需求与作用进程间通信的需求主要体现在以下几个方面:1. 数据共享:不同进程可能需要共享数据,以便实现信息的交换和共同处理。
2. 信息传递:进程之间可能需要进行消息的传递,以便进行协调和同步。
3. 资源共享:进程可能需要共享系统资源,如文件、设备等。
进程间通信的作用主要包括:1. 提高系统性能:进程间通信可以使不同进程并发执行,提高系统整体的运行效率。
2. 实现协作:不同进程之间可以交换信息、协调工作,实现更复杂的任务。
3. 实现分布式计算:通过进程间通信,可以将任务分布到不同的进程或计算机上进行并行处理。
二、进程间通信的方式在实际应用中,进程间通信可以通过多种方式来实现:1. 管道(Pipe):管道是一种半双工的通信方式,可以用于具有亲缘关系的进程之间进行通信。
常见的管道实现有匿名管道和有名管道。
2. 消息队列(Message Queue):消息队列是一种通过系统内核提供的消息缓冲区进行通信的方式,具有高度灵活性和可靠性。
3. 信号量(Semaphore):信号量是一种计数器,用于实现进程之间的同步和互斥操作,常用于控制对共享资源的访问。
4. 共享内存(Shared Memory):共享内存是一种将同一块物理内存映射到多个进程的通信方式,可以实现数据的快速共享。
5. 套接字(Socket):套接字是一种通信机制,可以用于实现不同计算机之间的进程间通信,常用于网络编程。
以上只是进程间通信的一些常见方式,实际上还有其他方式如信号、文件、RPC(远程过程调用)等。
在选择具体的通信方式时,需要根据实际场景需求进行综合考虑。
了解电脑操作系统的进程间通信
了解电脑操作系统的进程间通信电脑操作系统中的进程间通信是指不同进程之间进行数据传递和信息交换的过程。
进程是操作系统中的基本单位,它代表着一个正在运行的程序。
进程间通信的目的是实现多个进程之间的协作和数据共享,从而提高系统的效率和性能。
进程间通信的方式有多种,包括管道、消息队列、信号量、共享内存等。
下面将逐一介绍这些通信方式及其特点。
1. 管道管道是一种半双工的通信方式,它分为无名管道和有名管道。
无名管道只能在具有父子关系的进程之间通信,而有名管道可以在不相关的进程之间通信。
管道的通信方式是通过将数据写入一个进程的输出端,然后由另一个进程从输入端读取数据。
它适用于数据量较小且有顺序要求的通信场景。
2. 消息队列消息队列是一种存放在内核中的消息链表,在发送进程和接收进程之间传递数据。
发送进程将消息发送到队列中,接收进程从队列中读取消息。
消息队列可以实现不相关进程之间的通信,且可以同时处理多个发送和接收操作。
它适用于并发性要求较高的场景。
3. 信号量信号量是一种用于进程间同步和互斥的机制。
通过设置信号量的初值,进程可以通过对信号量进行P(等待)和V(释放)操作来实现对共享资源的互斥访问。
信号量可以用于解决生产者-消费者问题、读者-写者问题等经典的进程同步与互斥问题。
4. 共享内存共享内存是一种进程间共享数据的方法,多个进程可以直接访问同一块内存区域。
进程可以通过读写该内存区域来进行数据的交换和共享。
由于共享内存不涉及内核的切换和数据的拷贝,所以速度较快,但同时也要求进程之间的同步和互斥。
除了上述几种常用的进程间通信方式外,还有其他一些更高级的通信机制,如远程过程调用(RPC)、网络套接字等。
它们可以在不同的计算机之间实现进程间通信,扩展了通信的范围和方式。
在实际应用中,选择何种进程间通信方式取决于具体的业务需求和系统架构。
不同的通信方式有各自的优缺点,需要根据实际情况进行选择。
同时,为了确保通信的正确性和可靠性,应当在设计和实现过程中考虑进程同步、错误处理等因素。
C语言进程间通信方法
C语言进程间通信方法在多道程序设计中,不同的进程之间需要进行通信和协调,以实现数据交换和资源共享。
而在C语言中,有几种主要的进程间通信方法,包括管道、信号、共享内存和消息队列。
下面将逐一介绍这些方法的特点和应用场景。
1. 管道(Pipe)管道是一种半双工的通信方式,它可以在父进程和子进程之间创建一个用于通信的文件描述符。
管道可以分为匿名管道和命名管道两种。
匿名管道只能在具有亲缘关系的进程之间使用,使用函数pipe()可以创建一个管道,并返回两个文件描述符,分别用于读取和写入管道。
父进程可以将数据写入管道,子进程则从管道中读取数据。
命名管道则允许没有亲缘关系的进程之间进行通信,用于创建命名管道的函数为mkfifo()。
不同于匿名管道,命名管道可以在文件系统中创建一个特殊的文件,进程可以通过打开该文件进行通信。
2. 信号(Signal)信号是一种异步的通信方式,它用于通知进程发生了某个特定事件。
在C语言中,可以使用signal()函数来设置信号的处理函数。
进程可以通过发送信号给另一个进程来实现简单的通信。
信号的应用场景较为广泛,例如进程终止和异常处理。
当进程接收到信号时,可以根据信号的类型来执行相应的处理操作。
3. 共享内存(Shared Memory)共享内存允许多个进程之间访问同一块物理内存,以实现高效的数据共享。
进程可以使用shmget()函数创建一个共享内存区域,并使用shmat()函数将共享内存映射到本进程的地址空间中。
共享内存的好处在于数据传输效率高,因为进程直接访问内存而无需通过中介来实现通信。
然而,共享内存的使用需要更加小心,因为没有任何机制来保护共享数据的完整性和一致性。
4. 消息队列(Message Queue)消息队列是一种可以在不同进程之间传输数据的通信方式。
它允许将消息发送到消息队列中,并由其他进程从中读取。
消息的顺序按照发送的顺序进行。
通过调用msgget()函数可以创建或打开一个消息队列,而使用msgsnd()函数和msgrcv()函数分别用于发送和接收消息。
