学ucos至事件管理,事件之间将会有对话,开始拿本操做系统的书辅助理论上的理解。数组
参考《操做系统之哲学原理》,做者 邹恒明。安全
it's the map of this section.服务器
进程对白就是一个进程发出某种数据信息,另一方接受数据信息,而这些数据信息经过一片共享的存储空间进行传递。网络
管道所占空间能够是内存,也能够是磁盘。就像两我的对白的媒介能够是空气,也能够是线缆同样。要建立一个管道,一个进程只须要调用管道建立的系统调用便可。该系统调用所作的事情就是在某种存储介质上划出一片空间,赋给其中一个进程写的权利,另外一个进程读的权利便可。数据结构
从根本上说,管道是一个线性字节数组,相似文件。在其后谈论到管道和记名管道的缺点是提到,管道和记名管道并非因此操做系统都支持,主要支持管道通讯方式的是UNIX和类UNIX的操做系统,这使我想起everything is file这话。socket
在程序里面,建立管道须要使用系统调用popen()或者pipe()。popen()须要提供一个目标进程做为参数,而后调用该函数的进程和给出目标进程之间建立一个管道。函数
建立时还须要提供一个参数代表管道类型——读管道或者写管道。而pipe()调用将返回两个文件描述符,即一个用于识别文件流的整数,其中一个用于从管道进行读操做,一个用于写入管道。例如this
1 int pp[2]; 2 pipe(pp); 3 4 if(fork() == 0){ 5 read(pp[0]); 6 } 7 else{ 8 write(pp[1]) 9 }
管道的一个重要特色是使用管道的两个进程之间必须存在某种关系。spa
若是在两个不相关的进程(如两个不一样进程里的进程)之间进行管理通讯,则须要使用记名管道。记名管道是一个有名字的通讯管道,与文件系统共享一个名字空间,即不能与其余任何文件重名。操作系统
一个进程建立一个记名管道后,另一个进程可使用open来打开这个管道(五名管道不能使用open操做),从而与另一端交流。
记名管道的名称由两部分组成:计算机名和管道名。
对于同一主机来讲,容许有多个同一命名管道的实例而且能够由不一样的进程打开,可是不一样的管道都有属于本身的管道缓冲区并且有本身的通讯环境,互不影响。命名管道能够支持多个客户端链接一个服务器端,命名管道客户端不但能够与本机上的服务通讯,也能够同其余主机上的服务通讯。
套接字(socket)是另一种能够用于进程间通讯的机制,其功能很是强大,能够支持不一样层面、不一样应用、跨网络的通讯。
使用套接字进行通讯须要双方都建立一个套接字,其中一方做为服务器方,另外一方做为客户方。 服务器方必须先建立一个服务器套接字,而后在该套接字上进行监听,等待远方的链接请求。 欲与服务器通讯的客户则建立一个客户套接字,而后向服务区的套接字发送链接请求。 服务器套接字在收到链接请求以后,将在服务器方机器上建立一个客户套接字,与远方的客户机上的客户套接字造成点到点的通讯通道。 以后,客户方和服务器方就能够经过send和recv命令在这个建立的套接字通道上进行交流了。
例子略。
这里须要指出的是服务区套接字既不发送数据,也不接受数据(指不接受正常的用户数据,而不是链接请求数据),而仅仅生产出客户套接字。当其余的客户套接字发出一个链接请求时,咱们就建立一个客户套接字。一旦建立了客户套接字clientsocket,与客户通讯的任务就交给了这个刚刚建立的客户套接字。而本来的服务器套接字seversocket则回到其原来的监听操做上。
由于其强大的功能,套接字有许多种类,不一样的操做系统均支持或实现了某种套接字的功能。
而后做者blabla了套接字的类型,no interested, so just skip over.
管道和套接字同时也存在某些缺点。
首先,若是使用管道和套接字方式来通讯,必须事先在通讯的进程间创建链接(建立管道或者套接字),这须要消耗资源。
其次,通讯是自愿的。即一方虽然能够随意向管道或者套接字发送信息,但对方却能够选择接受的时机,这对发送方不是有利,若是应用到实时系统就违背了实时的原则。
再次,因为创建消耗链接时间,一旦创建,咱们就想进行尽量多的通讯。而若是通讯的信息量微小,则用管道和套接字有就些浪费资源了。
所以咱们选择用另一个机制,即信号,来应对上述的通讯需求:
在ucos里,有信号,应该不存在管道和socket吧。
在计算机里,信号就是一个内核对象,或者说是一个内核数据结构。发送方将该数据结构的内容填好,并指明该信号的目标进程后,发出特定的软件中断。操做系统接受到特定的中断请求后,知道是有进程要发送信号,因而到特定的内核数据结构里查找信号接收方,并进行通知。接到通知的进程则对信号进行相应处理。
做者在这里把信号量比做旗语——引用了火车的一个例子。
在一条单轨铁路上,任什么时候候只能有一列列车行驶在上面。而管理这条铁路的系统就是信号量。任什么时候候一列火车须要要等到代表铁路能够行驶的信号后才能进入轨道。当一列列车进入单轨运行以后,须要将信号改成禁止进入,从而防止别的火车同时进入轨道。而当列车驶出单轨以后,则须要将信号变为容许进入状态。
在计算机里,信号量实际上就是一个简单整数。一个进程在信号量(原书没有“量”字)变为0或者1的状况下推动,而且将信号量(原书没有“量”字)变为1或者0来防止别的进程推动。
(就像一个使能信号,好比这里的OS_EVENT_EN?
1 #if (OS_EVENT_EN) 2 void OS_EventWaitListInit (OS_EVENT *pevent) 3 { 4 #if OS_LOWEST_PRIO <= 63 5 INT8U *ptbl; 6 #else 7 INT16U *ptbl; 8 #endif 9 INT8U i; 10 11 12 pevent->OSEventGrp = 0; /* No task waiting on event */ 13 ptbl = &pevent->OSEventTbl[0]; 14 15 for (i = 0; i < OS_EVENT_TBL_SIZE; i++) { 16 *ptbl++ = 0; 17 } 18 } 19 #endif
)
须要注意的是,信号量不仅是一种通讯机制,更是一个同步机制。
管道、套接字、信号、信号量,虽然知足了多种通讯须要,但未考虑到两个进程通讯须要共享大量数据。这时便引出"共享内存"这个概念。
共享内存就是两个进程共同拥有同一片内存。对于这片内存中的任何内容,两者都可以访问。要实用共享内存进行通讯,一个进程须要首先建立一片内存空间专门做为通讯用,而其余进程则将该片内存映射到本身的(虚拟)地址空间。这样,读写本身地址空间中对应共享内存的区域时,就是在和其余进程进行通讯。如图(来源自书本)
共享内存与管道的区别在于:
共享内存的缺点是管理复杂和安全性弱。
这里须要注意的是,使用全局变量在同一个进程的进程间实现通讯不称为共享内存。
消息队列是一列具备头和尾的消息排列。新来的消息放在队列尾部,而读取消息则从队列头部开始。如图(来源于书本)
消息队列和管道的区别在于:
blabla,no interested