>  기사  >  시스템 튜토리얼  >  Linux IPC System V 메시지 큐: 안정적인 메시지 전달을 위한 고전적인 방법

Linux IPC System V 메시지 큐: 안정적인 메시지 전달을 위한 고전적인 방법

王林
王林앞으로
2024-02-12 15:33:151051검색

Linux 시스템은 다중 작업의 동시 실행을 지원하는 운영 체제로, 동시에 여러 프로세스를 실행할 수 있어 시스템 활용도와 효율성이 향상됩니다. 그러나 이러한 프로세스 간에 데이터 교환 및 협업이 필요한 경우 신호, 공유 메모리, 세마포어 등과 같은 일부 프로세스 간 통신(IPC) 방법을 사용해야 합니다. 그중 System V 메시지 큐는 비교적 고전적이고 안정적인 IPC 방법으로, 두 개 이상의 프로세스가 메시지의 내용과 형식을 고려하지 않고 큐를 통해 메시지를 전송할 수 있습니다. 이 기사에서는 메시지 큐의 생성, 열기, 전송, 수신, 닫기 및 삭제를 포함하여 Linux 시스템에서 System V 메시지 큐의 방법을 소개합니다.

Linux IPC System V 消息队列:一种实现可靠消息传递的经典方式

모델

으아악

ftok()

으아악

pathname: 파일 이름
proj_id: 1에서 255 사이의 숫자, project_id를 나타냄

으아악

msgget()

으아악

msgflg: 특정 작업 플래그

  • IPC_CREAT 존재하지 않으면 생성하세요. msgflg에 "|권한 정보"가 필요하면 엽니다.
  • IPC_EXCL존재하면 생성 실패
  • 0 기존 메시지 대기열 가져오기

메시지 대기열의 용량은 msg_qbytes에 의해 제어됩니다. 메시지 대기열을 생성하는 동안 이 크기는 MSGMNB로 초기화됩니다. 이 제한은 msgctl()

을 통해 수정할 수 있습니다. 으아악

msgsnd()

으아악

msqid msgget()이 반환한 메시지 큐의 ID
msgp메시지의 첫 번째 주소는 다음과 같습니다

으아악

msgsz메시지 크기 이 매개변수는 메시지 유형을 제외한 메시지 내용의 크기를 지정하는 데 사용됩니다. sizeof(Msgbuf)가 아닌 sizeof(Msgbuf.mtext)만 가능합니다
msgflg전송된 플래그, 기본값은 0

으아악

msgrcv()

으아악

msqid: 메시지 대기열의 ID(msgget에서 반환)
msgp: 수신된 메시지가 저장되는 버퍼의 첫 번째 주소
msgsz: 메시지 유형을 제외한 메시지의 최대 크기 메시지 ==> sizeof(Msgbuf.mtext)만 가능하며 sizeof(Msgbuf)는 불가능합니다

  • 메시지 길이가 msgsz보다 크고 msgflg에 MSG_NOERROR가 있으면 메시지가 잘리고 잘린 부분은 손실됩니다
  • 메시지 길이가 msgsz보다 크고 msgflg에 MSG_NOERROR가 없으면 오류가 발생하고 E2BIG가 보고됩니다.

msgtyp: 메시지 유형

  • 0: 메시지 대기열의 첫 번째 메시지 읽기
  • >0: 메시지 대기열에서 msgtype 유형의 첫 번째 메시지를 읽습니다. msg_flg에 MSG_EXCEPT가 없으면 대기열에서 msgtyp가 아닌 첫 번째 메시지가 읽혀집니다.
  • 메시지 대기열의 유형 읽기

msgflg: 보낼 플래그, 기본값은 0

Msg msg1;
int res=msgrcv(msqid,&msg1,sizeof(msg1.buf),1,0);
if(-1==res)
    perror("msgrcv"),exit(-1);

msgctl()

// 消息操作,成功返回0,失败返回-1设errno
int msgctl(int msqid, int cmd, struct msqid_ds *buf);

msqid :消息队列的ID,由msgget()
buf 结构体指针

struct msqid_ds {
    struct ipc_perm msg_perm;       /* Ownership and permissions */
    time_t          msg_stime;      /*Time of last msgsnd(2) */
    time_t          msg_rtime;      /* Time of last msgrcv(2) */
    time_t          msg_ctime;      /* Time of last change */
    unsigned long   __msg_cbytes;   /* Current number of bytes in queue (nonstandard) */
    msgqnum_t       msg_qnum;       /* Current number of messages in queue */
    msglen_t        msg_qbytes;     /* Maximum number of bytes allowed in queue */
    pid_t           msg_lspid;      /* PID of last msgsnd(2) */
    pid_t           msg_lrpid;      /* PID of last msgrcv(2) */
};
struct ipc_perm {
    key_t           __key;      /* Key supplied to msgget(2) */
    uid_t           uid;        /* Effective UID of owner */
    gid_t           gid;        /* Effective GID of owner */
    uid_t           cuid;       /* Effective UID of creator */
    gid_t           cgid;       /* Effective GID of creator */
    unsigned short  mode;       /* Permissions */
    unsigned short  __seq;      /* Sequence number */
};

cmd

  • IPC_STAT从内核相关结构体中拷贝消息队列相关的信息到buf指向的结构体中

  • IPC_SET把buf指向的结构体的内容写入到内核相关的结构体中,同时更显msg_ctimer成员,同时以下成员也会被更新:msg_qbytes, msg_perm.uid, msg_perm.gid, msg_perm.mode。调用队列的进程的effective UID必须匹配队列所有者或创建者的msg_perm.uid或msg_perm.cuid或者该进程拥有特权级别,

  • IPC_RMID立即销毁消息队列,唤醒所有正在等待读取或写入该消息队列进程,调用的进程的UID必须匹配队列所有者或创建者或者该进程拥有足够的特权级别

  • IPC_INFO (Linux-specific)返回整个系统对与消息队列的限制信息到buf指向的结构体中

    //_GNU_SOURCE
    //
    struct msginfo {
        int msgpool;/*Size in kibibytes of buffer pool used to hold message
     data; unused within kernel*/
        int msgmap; /*Maximum number of entries in message map; unused within 
    kernel*/
        int msgmax; /*Maximum number of bytes that can be written in a single
     message*/
        int msgmnb; /*Maximum number of bytes that can be written to queue; 
    used to initialize msg_qbytes  during queue creation*/
        int msgmni; /*Maximum number of message queues*/
        int msgssz; /*Message segment size; unused within kernel*/
        int msgtql; /*Maximum number of messages on all queues in system; unused
     within kernel*/
        unsigned short int  msgseg; /*Maximum number of segments; unused
     within kernel*/
    };
    
    int res=msgctl(msqid,IPC_RMID,NULL);
    if(-1==res)
    perror("msgctl"),exit(-1);
    

例子

//Sys V IPC msg
#include
#include
#include
#include
#include
typedef struct{
    long mtype;     //消息的类型
    char buf[20];       //消息的内容
}Msg;
int msqid;          //使用全局变量,这样就可以在fa中使用msqid了
void fa(int signo){
    printf("deleting..\n");
    sleep(3);
    int res=msgctl(msqid,IPC_RMID,NULL);
    if(-1==res)
        perror("msgctl"),exit(-1);
    exit(0);
}
int main(){
    //ftok()
    key_t key=ftok(".",150);
    if(-1==key)
        perror("ftok"),exit(-1);
    printf("key%#x\n",key);
    //msgget()
    msqid=msgget(key,IPC_CREAT|IPC_EXCL|0664);
    if(-1==msqid)
        perror("msgget"),exit(-1);
    printf("msqid%d\n",msqid);
    //msgsnd()
    Msg msg1={1,"hello"};//消息的类型是1,内容是hello
    Msg msg2={2,"world"};
    int res=msgsnd(msqid,&msg2,sizeof(msg2.buf),0);
    if(-1==res)
        perror("msgsnd"),exit(-1);
    res=msgsnd(msqid,&msg1,sizeof(msg1.buf),0);
    if(-1==res)
        perror("msgsnd"),exit(-1);
    //msgctl()
    //Ctrl+C delete msq
    printf("Press CTRL+C to delete msq\n");
    if(SIG_ERR==signal(SIGINT,fa))
        perror("signal"),exit(-1);
    while(1);
    return 0;
}

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

위 내용은 Linux IPC System V 메시지 큐: 안정적인 메시지 전달을 위한 고전적인 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 lxlinux.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제
이전 기사:리눅스 성능튜닝~다음 기사:리눅스 성능튜닝~