Maison > Tutoriel système > Linux > Linux IPC POSIX Message Queuing : un moyen simple d'assurer une livraison fiable des messages

Linux IPC POSIX Message Queuing : un moyen simple d'assurer une livraison fiable des messages

PHPz
Libérer: 2024-02-10 14:45:25
avant
790 Les gens l'ont consulté

Le système Linux est un système d'exploitation qui prend en charge l'exécution simultanée de tâches multiples. Il peut exécuter plusieurs processus en même temps, améliorant ainsi l'utilisation et l'efficacité du système. Cependant, si l'échange de données et la collaboration sont requis entre ces processus, certaines méthodes de communication inter-processus (IPC) doivent être utilisées, telles que les signaux, la mémoire partagée, les sémaphores, etc. Parmi eux, la file d'attente de messages POSIX est une méthode IPC relativement simple et fiable. Elle permet à deux processus ou plus de transmettre des messages via une file d'attente sans se soucier du contenu et du format du message. Cet article présentera les méthodes de file d'attente de messages POSIX dans le système Linux, y compris la création, l'ouverture, l'envoi, la réception, la fermeture et la suppression de la file d'attente de messages.

Linux IPC POSIX 消息队列:一种实现可靠消息传递的简单方式

Modèle :

#include
#include 
#include 
mq_open()   //创建/获取消息队列fd       
mq_get()    //设置/获取消息队列属性   
mq_send()/mq_receive()    //发送/接收消息 
mq_close()      //脱接消息队列            
mq_unlink()     //删除消息队列            
Copier après la connexion

Avantages de POSIX mq VS Sys V mq

  • Une interface d'application basée sur des fichiers plus simple
  • Prise en charge complète de la priorité des messages (la priorité détermine en fin de compte la position du message dans la file d'attente)
  • Prend entièrement en charge la notification asynchrone de l'arrivée du message, qui est implémentée via des signaux ou la création de fils de discussion
  • Mécanisme de délai d'attente pour bloquer les opérations d'envoi et de réception

Nom de la file d'attente des messages

C'est connu grâce à $man mq_overview : une file d'attente de messages est identifiée de manière unique par un nom sous la forme '/somename'. La longueur maximale de la chaîne de nom ne peut pas être supérieure à NAME_MAX (c'est-à-dire 255). nom de la file d'attente

mq_open()

//创建一个POSIX消息队列或打开一个已经存在的消息队列,成功返回消息队列描述符mqdes供其他函数使用,失败返回

(mqd_t)-1设errno
//Link with -lrt.
mqd_t mq_open(const char *name, int oflag);
mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr);
Copier après la connexion

oflag
doit inclure l'un des :

  • O_RDONLY signifie ouvrir la file d'attente des messages pour recevoir uniquement des messages
  • O_WRONLY signifie ouvrir la file d'attente des messages pour envoyer uniquement des messages
  • O_RDWR signifie ouvrir la file d'attente des messages sous une forme qui peut être reçue et envoyée

peut être binaire ORed :

  • O_NONBLOCKOuvrez la file d'attente des messages en mode non bloquant
  • O_CREATSi une file d'attente de messages n'existe pas, créez-la. L'UID du propriétaire de la file d'attente de messages est défini sur l'UID effectif du processus appelant, et le GID est défini sur le GID effectif du processus appelant
  • O_EXCLAssurez-vous que la file d'attente des messages est créée, si la file d'attente des messages existe déjà, une erreur se produit

modeS'il y a O_CREAT dans oflag, mode est utilisé pour représenter les autorisations de la file d'attente de messages nouvellement créée
attrS'il y a O_CREAT dans oflag, alors attr représente les attributs de la file d'attente de messages. Si attr est NULL. , ce sera par défaut. Définissez la file d'attente des messages de configuration (mq_overview(7) pour plus de détails.)

mq_setattr() / mq_getattr()

//设置/修改 / 获取消息队列属性,成功返回0,失败返回-1设errno
//Link with -lrt.
int mq_setattr(mqd_t mqdes, const struct mq_attr *newattr, struct mq_attr *oldattr);
int mq_getattr(mqd_t mqdes, struct mq_attr *attr);
Copier après la connexion

structure mqattr

struct mq_attr {
    long mq_flags;      /* Flags: 0 or O_NONBLOCK */
    long mq_maxmsg;     /* Max. # of messages on queue */
    long mq_msgsize;    /* Max. message size (bytes) */
    long mq_curmsgs;    /* # of messages currently in queue */
};
Copier après la connexion

mq_send() / mq_timesend()

//发送消息到mqdes指向的消息队列。成功返回0,失败返回-1设errno
//Link with -lrt.
int mq_send(mqd_t mqdes, const char *msg_ptr,size_t msg_len, unsigned int msg_prio);

//如果消息队列满
#include        //额外的header
int mq_timedsend(mqd_t mqdes, const char *msg_ptr,size_t msg_len, unsigned int msg_prio,
const struct timespec *abs_timeout);
Copier après la connexion

msg_len msg_ptr指向的消息队列的长度,这个长度必须msg_prio 一个用于表示消息优先级的非0整数,消息按照优先级递减的顺序被放置在消息队列中,同样优先级的消息,新的消息在老的之后,如果消息队列满了,就进入blocked状态,新的消息必须等到消息队列有空间了进入,或者调用被signal中断了。如果flag里有O_NOBLOCK选项,则此时会直接报错
abs_timeout:如果消息队列满了,那么就根据abs_timeout指向的结构体表明的时间进行锁定,里面的时间是从970-01-01 00:00:00 +0000 (UTC)开始按微秒计量的时间,如果时间到了,那么mq_timesend()立即返回

struct timespec {
    time_t tv_sec;        /* seconds */
    long   tv_nsec;       /* nanoseconds */
};
Copier après la connexion

mq_receive()/mq_timedreceive()

//从消息队列中取出优先级最高的里面的最老的消息,成功返回消息取出消息的大小,失败返回-1设errno
//具体功能参照mq_send()/mq_timesend()
//Link with -lrt.
ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio);
#include        //额外的header
ssize_t mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len,
 unsigned int *msg_prio, const struct timespec *abs_timeout);
Copier après la connexion

mq_notify()

//允许调用进程注册或去注册同步来消息的通知,成功返回0,失败返回-1设errno
//Link with -lrt.
int mq_notify(mqd_t mqdes, const struct sigevent *sevp);
Copier après la connexion

sevp指向sigevent的指针

  • 如果sevp不是NULL,那么这个函数就将调用进程注册到通知进程,只有一个进程可以被注册为通知进程
  • 如果sevp是NULL且当前进程已经被注册过了,则去注册,以便其他进程注册
union sigval {                  /* Data passed with notification */
    int     sival_int;          /* Integer value */
    void*   sival_ptr;          /* Pointer value */
};
struct sigevent {
    int     sigev_notify;       /* Notification method */
    int     sigev_signo;        /* Notification signal */
    union sigval    sigev_value;    /* Data passed with notification */
    void(*sigev_notify_function) (union sigval); //Function used for thread notification
 (SIGEV_THREAD)
    void*   sigev_notify_attributes;    // Attributes for notification thread (SIGEV_THREAD)
    pid_t   sigev_notify_thread_id;     /* ID of thread to signal (SIGEV_THREAD_ID) */
};
Copier après la connexion

sigev_notify使用下列的宏进行配置:

  • SIGEV_NONE调用进程仍旧被注册,但是有消息来的时候什么都不通知
  • SIGEV_SIGNAL通过给调用进程发送sigev_signo指定的信号来通知进程有消息来了
  • SIGEV_THREAD一旦有消息到了,就激活sigev_notify_function作为新的线程的启动函数

mq_close()

//关闭消息队列描述符mqdes,如果有进程存在针对这个队列的notification request,那么也会被移除

//成功返回0,失败返回-1设errno
//Link with -lrt.
int mq_close(mqd_t mqdes);
Copier après la connexion

mq_unlink():

//移除队列名指定的消息队列,一旦最后一个进程关闭了针对这个消息队列的描述符,就会销毁这个消息队列
//成功返回0,失败返回-1设errno
//Link with -lrt.
int mq_unlink(const char *name);
Copier après la connexion

本文介绍了Linux系统中POSIX 消息队列的方法,包括消息队列的创建、打开、发送、接收、关闭和删除等方面。通过了解和掌握这些知识,我们可以更好地使用POSIX 消息队列来实现进程间通信,提高系统的稳定性和效率。当然,Linux系统中POSIX 消息队列还有很多其他的特性和用法,需要我们不断地学习和研究。希望本文能给你带来一些启发和帮助。

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:lxlinux.net
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal