ホームページ  >  記事  >  システムチュートリアル  >  Linux IPC POSIX メッセージ キュー: 信頼性の高いメッセージ配信を実現する簡単な方法

Linux IPC POSIX メッセージ キュー: 信頼性の高いメッセージ配信を実現する簡単な方法

PHPz
PHPz転載
2024-02-10 14:45:25729ブラウズ

Linux システムは、マルチタスクの同時実行をサポートするオペレーティング システムであり、複数のプロセスを同時に実行できるため、システムの使用率と効率が向上します。ただし、これらのプロセス間でデータ交換とコラボレーションが必要な場合は、シグナル、共有メモリ、セマフォなどのプロセス間通信 (IPC) メソッドを使用する必要があります。その中でも、POSIX メッセージ キューは比較的シンプルで信頼性の高い IPC 方式であり、複数のプロセスがメッセージの内容や形式を気にせずにキューを介してメッセージを送信できます。この記事では、メッセージキューの作成、オープン、送信、受信、クローズ、削除など、LinuxシステムでのPOSIXメッセージキューの方法を紹介します。

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

######モデル:###### リーリー

POSIX mq と Sys V mq の利点

よりシンプルなファイルベースのアプリケーション インターフェイス

    メッセージ優先度の完全なサポート (優先度は最終的にキュー内のメッセージの位置を決定します)
  • メッセージ到着の非同期通知を完全にサポートします。これはシグナルまたはスレッド作成を通じて実装されます
  • 送受信操作をブロックするためのタイムアウト メカニズム
  • メッセージキュー名

$man mq_overview から判明: メッセージ キューは '/somename' の形式の名前によって一意に識別されます。名前文字列の最大長は NAME_MAX (つまり 255) を超えることはできません。 2 つのプロセスが同じメッセージ キュー名を使用して通信する

mq_open()

リーリー

オフラグ

次のいずれかを含める必要があります:


O_RDONLY

は、メッセージを受信するためだけにメッセージ キューを開くことを意味します
  • O_WRONLY は、メッセージを送信するためだけにメッセージ キューを開くことを意味します
  • O_RDWR メッセージキューを送受信可能な形式でオープンすることを示します
  • はビット単位の論理和演算が可能:

O_NONBLOCK

ノンブロッキング モードでメッセージ キューを開きます
  • O_CREATメッセージ キューが存在しない場合は、メッセージ キューを作成します。メッセージ キューの所有者の UID は呼び出しプロセスの実効 UID に設定され、GID は呼び出しプロセスの実効 GID に設定されます。プロセス######
  • O_EXCL メッセージ キューが作成されていることを確認します。メッセージ キューがすでに存在する場合、エラーが発生します。
  • modeoflag に O_CREAT がある場合、mode は新しく作成されたメッセージ キューの権限を表すために使用されます。
  • attr
oflag に O_CREAT がある場合の場合、attr はメッセージ キューの属性を表します。attr が NULL の場合、メッセージ キューはデフォルト設定に従って構成されます (詳細については mq_overview(7))。

mq_setattr() / mq_getattr()
リーリー 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 */
};

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);

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 */
};

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);

mq_notify()

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

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) */
};

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);

mq_unlink():

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

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

以上がLinux IPC POSIX メッセージ キュー: 信頼性の高いメッセージ配信を実現する簡単な方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はlxlinux.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。