NuttX的学习笔记 10

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yt454287063/article/details/53843128

Named Message Queue Interfaces

命名消息队列的接口
NuttX支持POSIX命名消息队列inter-task通讯。任何任务都能能通过命名消息队列发送或接收消息。中断处理程序可以通过命名消息队列发送消息。我理解就是进程之间通讯需要一个消息通道,消息队列就是这样一个通道,而其标识就是这个“Named”。

mq_open

mqd_t mq_open(const char *mqName, int oflags, …);

调用这个函数将与一个消息队列链接。
oflags:

oflags 意义
O_RDONLY 读访问
O_WRONLY 写访问
O_RDWR 读和写
O_CREAT 如果不存在时创建消息队列。
O_EXCL 打开时名称必须不存在
O_NONBLOCK 不要等待数据。

.
这是一个参数数量可变的函数,根据头文件中的描述,当 O_CREAT 这个oflags被使用时,该函数将另外需要两个参数:mode_t modestruct mq_attr *attr

mode 这里说的是权限,就像在Linux中文件的权限一样。相关定义:

#define S_IXOTH|  0000001 /* Permissions for others: Run only */
#define S_IWOTH     0000002 /* Permissions for others: Write only */
#define S_IROTH     0000004 /* Permissions for others: Read only */
#define S_IRWXO     0000007 /* Permissions for others: All */

#define S_IXGRP     0000010 /* Group permissions: Run only */
#define S_IWGRP     0000020 /* Group permissions: Write only */
#define S_IRGRP     0000040 /* Group permissions: Read only */
#define S_IRWXG     0000070 /* Group permissions: All */

#define S_IXUSR     0000100 /* Owner permissions: Run only */
#define S_IWUSR     0000200 /* Owner permissions: Write only */
#define S_IRUSR     0000400 /* Owner permissions: Read only */
#define S_IRWXU     0000700 /* Owner permissions: All */

struct mq_attr *attr

可以找到定义:

struct mq_attr {
    size_t mq_maxmsg;  /* Max number of messages in queue */
    size_t mq_msgsize; /* Max message size */
    unsigned mq_flags; /* Queue flags */
    size_t mq_curmsgs; /* Number of messages currently in queue */
};

看起来是一些属性。

*我决定每一个函数函数后都加上测试,然后发现这个直接上来就写有点难,然后全工程搜索,发现了一个叫ostest的例子。细细一看,尽然包含了之前所有的函数,简直没天理啊。。将其下mqueue.c文件中的代码拷过来,加个宏定义居然就能用了。我先试试开启这个例子把。结果是完全能用,真后悔没有早点发现这个例子。有空把前面的坑全都补上。包括那个等待所有子进程的坑。所有有关进程锁,消息队列的例子代码都在这个ostest里面*

mq_close

int mq_close(mqd_t mqdes);

这个函数是用来表明调用任务已经完成了指定描述符的消息排队。mq_close()收回分配任何系统资源分配的系统消息队列使用的这个任务。

简单的来说就是关闭消息队列。通过参数也就是消息队列的描述符。

int mq_unlink(const char *mqName);

这个函数使用来删除消息队列,如果消息队列已经被打开,那么将等到其被关闭时再删除。

mq_send

int mq_send(mqd_t mqdes, const void *msg, size_t msglen, int prio);

这个函数将一个大小为msglen bytes的信息(由msg指向的字符串)添加到由消息队列描述符mqdes指定的消息队列中。最大长度不得超过由mq_getattr()获得的长度。这里,mq_getattr()返回的是一个结构体:

struct mq_attr {
  size_t mq_maxmsg; /* Max number of messages in queue */
  size_t mq_msgsize; /* Max message size */
  unsigned mq_flags; /* Queue flags */
  size_t mq_curmsgs; /* Number of messages currently in queue */
};

这里所指的是成员mq_msgsize

这里对应三种情况:

  • 如果消息队列未满,函数将信息插入消息队列中优先级为prio - 1的消息的前面。
  • 如果消息队列已满,并且O_NONBLOCK没有置位,那么函数将阻塞,直到消息队列有地方可存放。
  • 如果消息队列已满,并且O_NONBLOCK置位,那么函数将返回错误。

正确返回OK;错误返回ERROR并返回错误代码:

errno 详细
EAGAIN 消息队列为空,且O_NONBLOCK置位
EINVAL 参数有错
EPERM 消息队列打开方式不可写
EMSGSIZE 长度超出
EINTR 调用时被中断

.

mq_receive

ssize_t mq_receive(mqd_t mqdes, void *msg, size_t msglen, int *prio);

函数将接受最高优先级中存放时间最久的信息。如果msg指向的空间不足以存放信息,那么函数将返回错误。否则,信息将从队列中移动到msg指向的空间内。

如果队列为空且O_NONBLOCK没有置位,那么函数将锁定直到队列中有信息。如果有很多任务在等待,那么只有等待时间最久的优先级最高的任务才能解锁。

如果队列为空且O_NONBLOCK置位,那么函数将返回错误和错误参数。

errno 详细
EAGAIN 消息队列为空,且O_NONBLOCK置位
EPERM 消息队列打开方式不可写
EMSGSIZE 长度超出
EINTR 调用时被中断
EINVAL 参数有错

.

mq_timedreceive

ssize_t mq_timedreceive(mqd_t mqdes, void *msg, size_t msglen, int *prio, const struct timespec *abstime);

函数将接受最高优先级中存放时间最久的信息。如果msg指向的空间不足以存放信息,那么函数将返回错误。否则,信息将从队列中移动到msg指向的空间内。

如果队列为空且O_NONBLOCK没有置位,那么函数将锁定直到队列中有信息。如果有很多任务在等待,那么只有等待时间最久的优先级最高的任务才能解锁。

唯一一点不同的是,如果O_NONBLOCK没有被启用,那么函数将会等待一段时间,由结构体abstime来确定,之后没有消息的话将立刻返回。
注意:这里是绝对时间。要先获取当前系统时间,然后在加上需要等待的时间。

errno 详细
EAGAIN 消息队列为空,且O_NONBLOCK置位
EPERM 消息队列打开方式不可写
EMSGSIZE 长度超出
EINTR 调用时被中断
EINVAL 参数有错
ETIMEDOUT 超时

.

mq_notify

int mq_notify(mqd_t mqdes, const struct sigevent *notification);

调用该函数的任务将注册为接受消息队列(由消息队列描述符mqdes指定)的通知。

如果notification输入参数不为NULL,当消息队列从空状态变为非空状态时,函数将发送一个信号到注册该消息队列通知的任务。

如果notification输入参数为NULL,那么已存在的注册将被分离(如果当前进程已经注册为接收指定队列的通知),消息队列将可用于注册为其他信号。

当信号notification被发送至进程后,该注册将被移除,消息队列可用于新的注册。

notification由实时信号结构体sigevent定义:

struct sigevent {
  uint8_t sigev_notify;     /* Notification method: SIGEV_SIGNAL, SIGEV_NONE, or SIGEV_THREAD */
  uint8_t sigev_signo;      /* Notification signal */
  union sigval sigev_value; /* Data passed with notification */
};

这里解释一下:

sigev_notify 意义
SIGEV_SIGNAL sigev_signo发送到进程
SIGEV_NONE 空的通知
SIGEV_THREAD 根据后面的定义看起来,该方法没有效果或者不可用,先忽略

.

由于这个ostest很重要,就先写到这里。有机会再补。

猜你喜欢

转载自blog.csdn.net/yt454287063/article/details/53843128