检查队列是否填满
39~48 如果调用者指定的队列已填满,但是o_NONBLOCK标志已设置,我们就返回一个EAGAIN错误。否则,我们等待在条件变量mqh_wait上,该条件变量由我们的mq_receive函数在从某个填满的队列中读出一个消息时发给信号。
就mq_send调用在被某个由其调用进程捕获的信号中断时返回一个EINTR错误而言,我们的实现简化了。问题在于当信号处理程序返回时,pthread_cond_wait并不返回一个错误:它可能返回一个为0的值(这看来是次虚假的唤醒),也可能根本不返回。绕过这一问题的方法确实存在,但每种方法都不简单。
图5—30给出了mq_send函数的后半部分。至此我们已知道调用者指定的队列中有写入新消息的空间。
取得待用空闲块的索引
50~52 既然在调用者指定的队列初始化时创建的空闲消息数等于mq_maxmsg,我们就不应该有在空闲链表为空的前提下mq_curmsgs小于mq_maxmsg的状态。
复制消息
53~56 nmsghdr含有所映射内存区中用于存放待写入消息的位置的地址。该消息的优先级和长度存放在它的msg_hdr结构中,其内容则从调用者空间复制。
把新消息置于链表中正确位置
57~74 我们的链表中各消息的顺序是从开始处(mqh_head)的最高优先级到结束处的最低优先级。当一个新消息加入调用者指定的队列中,并且一个或多个同样优先级的消息已在该队列中时,这个新消息就加在最后一个优先级相同的消息之后。使用这样的排序方式后,mq_receive总是返回链表中的第一个消息(它是该队列上优先级最高的最早的消息)。当我们沿链表行进时,pmsghdr将含有链表中上一个消息的地址,因为它的msg_next值将含有该新消息的索引。
……