嵌入式应用程序设计 教学课件 ppt 华清远见嵌入式学院 穆煜 第4章 嵌入式Linux进程间通信

上传人:E**** 文档编号:89376022 上传时间:2019-05-24 格式:PPT 页数:44 大小:846KB
返回 下载 相关 举报
嵌入式应用程序设计 教学课件 ppt 华清远见嵌入式学院 穆煜 第4章 嵌入式Linux进程间通信_第1页
第1页 / 共44页
嵌入式应用程序设计 教学课件 ppt 华清远见嵌入式学院 穆煜 第4章 嵌入式Linux进程间通信_第2页
第2页 / 共44页
嵌入式应用程序设计 教学课件 ppt 华清远见嵌入式学院 穆煜 第4章 嵌入式Linux进程间通信_第3页
第3页 / 共44页
嵌入式应用程序设计 教学课件 ppt 华清远见嵌入式学院 穆煜 第4章 嵌入式Linux进程间通信_第4页
第4页 / 共44页
嵌入式应用程序设计 教学课件 ppt 华清远见嵌入式学院 穆煜 第4章 嵌入式Linux进程间通信_第5页
第5页 / 共44页
点击查看更多>>
资源描述

《嵌入式应用程序设计 教学课件 ppt 华清远见嵌入式学院 穆煜 第4章 嵌入式Linux进程间通信》由会员分享,可在线阅读,更多相关《嵌入式应用程序设计 教学课件 ppt 华清远见嵌入式学院 穆煜 第4章 嵌入式Linux进程间通信(44页珍藏版)》请在金锄头文库上搜索。

1、嵌入式应用程序设计 第4章 嵌入式Linux进程间通信,2,第1章 搭建嵌入式Linux开发环境 第2章 嵌入式文件I/O编程 第3章 嵌入式Linux多任务编程 第4章 嵌入式Linux进程间通行 第5章 嵌入式Linux多线程编程 第6章 嵌入式Linux网络编程 第7章 Qt图形编程 第8章 嵌入式Linux设备驱动编程 第9章 Qt聊天项目设计,课程安排:,3,4.1 Linux下进程间通信概述 4.2 管道通信 4.3 信号通信 4.4 信号量 4.5 共享内存 4.6 消息队列 4.7 实验内容 4.8 小结 4.9 思考与练习,本章课程:,4,继承Unix平台上进程通信手段 集合

2、System V IPC(贝尔实验室)和socket的进程间通信机制(BSD)的优势,4.1 Linux下进程间通信概述,5,常用的进程间通信机制 管道及有名管道 信号 消息队列 共享内存 信号量 套接字,4.1 Linux下进程间通信概述,6,4.2.1 管道简介 无名管道特点 它只能用于具有亲缘关系的进程之间的通信(也就是父子进程或者兄弟进程之间)。 它是一个半双工的通信模式,具有固定的读端和写端。 管道也可以看成是一种特殊的文件,对于它的读写也可以使用普通的read()、write()等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中 有名管道特点 它可以使互不相

3、关的两个进程实现彼此通信。 该管道可以通过路径名来指出,并且在文件系统中是可见的。在建立了管道之后,两个进程就可以把它当作普通文件一样进行读写操作,使用非常方便。 FIFO严格地遵循先进先出规则,对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾,它们不支持如lseek()等文件定位操作。,4.2 管道通信,7,4.2.2 无名管道系统调用 管道创建和关闭 管道是基于文件描述符的通信方式,当一个管道建立时,它会创建两个文件描述符fds0和fds1,其中fds0固定用于读管道,而fd1固定用于写管道,这样就构成了一个半双工的通道。,4.2 管道通信,8,4.2.2 无名管道系

4、统调用 pipe() 创建管道可以通过调用pipe()来实现. pipe()语法:,4.2管道通信,9,4.2.2 无名管道系统调用 父子进程管道的文件描述符对应关系,4.2管道通信,10,4.2.2 无名管道系统调用 管道读写注意点: 只有在管道的读端存在时,向管道写入数据才有意义。否则,向管道写入数据的进程将收到内核传来的SIGPIPE信号(通常为Broken pipe错误)。 向管道写入数据时,Linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。如果读进程不读取管道缓冲区中的数据,那么写操作将会一直阻塞。 父子进程在运行时,它们的先后次序并不能保证,因此

5、,在为了保证父子进程已经关闭了相应的文件描述符,可在两个进程中调用sleep()函数,当然这种调用不是很好的解决方法,在后面学到进程之间的同步与互斥机制之后,请读者自行修改本小节的实例程序。,4.2管道通信,11,4.2.3 标准流管道 标准流管道函数说明 与Linux的文件操作中有基于文件流的标准I/O操作一样,管道的操作也支持基于文件流的模式。这种基于文件流的管道主要是用来创建一个连接到另一个进程的管道,这里的“另一个进程”也就是一个可以进行一定操作的可执行文件 。,4.2管道通信,12,4.2.3 标准流管道 popen函数格式: pclose函数格式:,4.2管道通信,13,4.2.3

6、 有名管道(FIFO) 通过mkfifo()创建有名管道 mkfifo()函数语法:,4.2管道通信,14,4.2.3 有名管道(FIFO) FIFO相关出错信息,4.2 管道通信,15,4.2.3 有名管道(FIFO) FIFO读写 对于读进程 若该管道是阻塞打开,且当前FIFO内没有数据,则对读进程而言将一直阻塞到有数据写入。 若该管道是非阻塞打开,则不论FIFO内是否有数据,读进程都会立即执行读操作。即如果FIFO内没有数据,则读函数将立刻返回0。 对于写进程 若该管道是阻塞打开,则写操作将一直阻塞到数据可以被写入。 若该管道是非阻塞打开而不能写入全部数据,则读操作进行部分写入或者调用失

7、败。,4.2 管道通信,16,4.3.1 信号概述 信号是在软件层次上对中断机制的一种模拟,是一种异步通信方式 信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用它来通知用户空间进程发生了哪些系统事件。它可以在任何时候发给某一进程,而无需知道该进程的状态。 如果该进程当前并未处于执行态,则该信号就由内核保存起来,直到该进程恢复执行再传递给它;如果一个信号被进程设置为阻塞,则该信号的传递被延迟,直到其阻塞被取消时才被传递给进程,4.3 信号通信,17,4.3.1 信号概述 进程相应信号的方式 忽略信号,即对信号不做任何处理,其中,有两个信号不能忽略:SIGKILL及SIGSTO

8、P。 捕捉信号,定义信号处理函数,当信号发生时,执行相应的处理函数。 执行缺省操作,Linux对每种信号都规定了默认操作,4.3 信号通信,18,4.3.1 信号概述 信号缺省操作,4.3 信号通信,19,4.3.2 信号发送和捕捉 信号发送:kill()和raise() kill()函数同读者熟知的kill系统命令一样,可以发送信号给进程或进程组,它不仅可以中止进程(实际上发出SIGKILL信号),也可以向进程发送其他信号。 kill()函数语法:,4.3 信号通信,20,4.3.2 信号发送和捕捉 信号捕捉:alarm()、pause() alarm()也称为闹钟函数,它可以在进程中设置一

9、个定时器,当定时器指定的时间到时,它就向进程发送SIGALARM信号 。 pause()函数是用于将调用进程挂起直至捕捉到信号为止。这个函数很常用,通常可以用于判断信号是否已到。,4.3 信号通信,21,4.3.2 信号发送和捕捉 信号的处理:signal、sigaction signal()处理信号时,只需要指出要处理的信号和处理函数即可。它主要是用于前32种非实时信号的处理,不支持信号传递信息,但是由于使用简单、易于理解,因此也受到很多程序员的欢迎 。 signal()函数的语法:,4.3 信号通信,22,4.3.2 信号发送和捕捉 信号的处理:signal、sigaction sigac

10、tion() 函数相对于signal()更加健壮,推荐使用这个,4.3 信号通信,23,4.3.2 信号发送和捕捉 信号的处理:signal、sigaction sigaction()函数中第2个和第3个参数用到的sigaction结构 struct sigaction void (*sa_handler)(int signo); sigset_t sa_mask; int sa_flags; void (*sa_restore)(void); sa_handler是一个函数指针,指定信号处理函数,这里除可以是用户自定义的处理函数外,还可以为SIG_DFL(采用缺省的处理方式)或SIG_IGN

11、(忽略信号)。它的处理函数只有一个参数,即信号值。 sa_mask是一个信号集,它可以指定在信号处理程序执行过程中哪些信号应当被屏蔽,在调用信号捕获函数之前,该信号集要加入到信号的信号屏蔽字中。 sa_flags中包含了许多标志位,是对信号进行处理的各个选择项,4.3 信号通信,24,4.4.1 信号量概述 信号量是用来解决进程之间的同步与互斥问题的一种进程之间通信机制,包括一个称为信号量的变量和在该信号量下等待资源的进程等待队列,以及对信号量进行的两个原子操作(PV操作)。其中信号量对应于某一种资源,取一个非负的整型值。信号量值指的是当前可用的该资源的数量,若它等于0则意味着目前没有可用的资

12、源。 PV原子操作的具体定义为: P操作:如果有可用的资源(信号量值0),则占用一个资源(给信号量值减去一,进入临界区代码);如果没有可用的资源(信号量值等于0),则被阻塞到,直到系统将资源分配给该进程(进入等待队列,一直等到资源轮到该进程)。 V操作:如果在该信号量的等待队列中有进程在等待资源,则唤醒一个阻塞进程。如果没有进程等待它,则释放一个资源(给信号量值加一)。,4.4 信号量,25,4.4.2 信号量编程 使用信号量的步骤: 第一步:创建信号量或获得在系统已存在的信号量,此时需要调用semget()函数。不同进程通过使用同一个信号量键值来获得同一个信号量。 第二步:初始化信号量,此时

13、使用semctl()函数的SETVAL操作。当使用二维信号量时,通常将信号量初始化为1。 第三步:进行信号量的PV操作,此时调用semop()函数。这一步是实现进程之间的同步和互斥的核心工作部分。 第四步:如果不需要信号量,则从系统中删除它,此时使用semclt()函数的IPC_RMID操作。此时需要注意,在程序中不应该出现对已经被删除的信号量的操作。,4.4 信号量,26,4.4.2 信号量编程 semget()函数语法:,4.4 信号量,27,4.4.2 信号量编程 semctl()函数语法:,4.4 信号量,28,4.4.2 信号量编程 semop()函数语法:,4.4 信号量,29,共

14、享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝 为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间 进程就可以直接读写这一内存区而不需要进行数据的拷贝,从而大大提高的效率。 由于多个进程共享一段内存,因此也需要依靠某种同步机制,如互斥锁和信号量等,4.5 共享内存,30,共享内存原理示意图,4.5 共享内存,31,共享内存实现的步骤: 创建共享内存,这里用到的函数是shmget,也就是从内存中获得一段共享内存区域 映射共享内存,也就是把这段创建的共享内存映射到具体的进程空间中去,这里使用的函数是shmat 到

15、这里,就可以使用这段共享内存了,也就是可以使用不带缓冲的I/O读写命令对其进行操作 撤销映射的操作,其函数为shmdt,4.5 共享内存,32,shmget函数语法:,4.5 共享内存,33,shmat函数语法:,4.5 共享内存,34,shmdt函数语法:,4.5 共享内存,35,消息队列就是一些消息的列表。用户可以在消息队列中添加消息和读取消息等。从这点上看,消息队列具有一定的FIFO特性,但是它可以实现消息的随机查询,比FIFO具有更大的优势。同时,这些消息又是存在于内核中的,由“队列ID”来标识。,4.6 消息队列,36,消息队列的实现包括创建或打开消息队列、添加消息、读取消息和控制消

16、息队列这四种操作 创建或打开消息队列使用的函数是msgget,这里创建的消息队列的数量会受到系统消息队列数量的限制 添加消息使用的函数是msgsnd函数,它把消息添加到已打开的消息队列末尾 读取消息使用的函数是msgrcv,它把消息从消息队列中取走,与FIFO不同的是,这里可以指定取走某一条消息 控制消息队列使用的函数是msgctl,它可以完成多项功能。,4.6 消息队列,37,msgget函数语法:,4.6 消息队列,38,msgsnd函数语法:,4.6 消息队列,39,msgrcv函数语法:,4.6 消息队列,40,msgctl函数语法:,4.6 消息队列,41,4.7.1 共享内存实验 实验目的 通过编写共享内存实验,读者可以进一步了解使用共享内存的具体步骤,同时也进一步加深对共享内存的理解。在本实验中,采用信号量作为同步机制完善两个进程(“生产者”和“消费者”)之间的通信。其功能类似于“消息队列”小节中的实例。在实例中使用信号量同步机制。 实验内容 该实现要求利用共享内存实

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 高等教育 > 大学课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号