Sistem Linux ialah sistem pengendalian yang menyokong pelaksanaan serentak pelbagai tugas Ia boleh menjalankan berbilang proses pada masa yang sama, dengan itu meningkatkan penggunaan dan kecekapan sistem. Walau bagaimanapun, jika pertukaran data dan kerjasama diperlukan antara proses ini, beberapa kaedah komunikasi antara proses (IPC) perlu digunakan, seperti isyarat, memori dikongsi, semaphore, dsb. Antaranya, baris gilir mesej Sistem V adalah kaedah IPC yang agak klasik dan boleh dipercayai Ia membenarkan dua atau lebih proses menghantar mesej melalui baris gilir tanpa mengambil berat tentang kandungan dan format mesej. Artikel ini akan memperkenalkan kaedah baris gilir mesej Sistem V dalam sistem Linux, termasuk penciptaan, pembukaan, penghantaran, penerimaan, penutupan dan pemadaman baris gilir mesej.
#include #include #include ftok() //获取key值 msgget() //创建/获取消息队列 msgsnd()/msgrcv() //发消息到消息队列/从消息队列收信息 msgctl() //删除消息队列
//获取key值, key值是System V IPC的标识符,成功返回key,失败返回-1设errno //同pathname+同 proj_id==>同key_t; key_t ftok(const char *pathname, int proj_id);
pathname: nama fail
proj_id: nombor dari 1 hingga 255, mewakili project_id
key_t key=ftok(".",100); //“.”就是一个存在且可访问的路径, 100是假设的proj_id if(-1==key) perror("ftok"),exit(-1);
//创建/获取消息队列,成功返回shmid,失败返回-1 int msgget(key_t key, int msgflg); //ATTENTION:用int msqid=msgget()比较好看
msgflg: bendera operasi khusus
int msqid=msgget(key,IPC_CREAT|IPC_EXCL|0664); if(-1==msqid) perror("msgget"),exit(-1);
//向指定的消息队列发送指定的消息,如果消息队列已经满了,默认的行为是堵塞,直到队列有空间容纳新的消息,成 功返回0,失败返回-1设errno int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
ID baris gilir mesej yang dikembalikan oleh msgget()msgp
Alamat pertama mesej Jenis data rujukan mesej adalah seperti berikut
struct msgbuf {
long mtype; /* message type, must be > 0 */ //消息的类型
char mtext[1]; /* message data */ //消息的内容
};
ATTENTION:The mtext field is an array (or other structure) whose size is
specified by msgsz, a nonnegative integer value.
Saiz mesej Parameter ini digunakan untuk menentukan saiz kandungan mesej, tidak termasuk jenis mesej. Ia hanya boleh saiz(Msgbuf.mtext), bukan saiz(Msgbuf)msgflg
Bendera dihantar, lalai ialah 0
Msg msg1={1,"hello"};//消息的类型是1,内容是hello
int res=msgsnd(msqid,&msg2,sizeof(msg2.buf),0);
if(-1==res)
perror("msgsnd"),exit(-1);
//向指定的消息队列取出指定的消息,成功返回实际接受到的byte数,失败返回-1设errno ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
: ID baris gilir mesej (dikembalikan oleh msgget) msgp
: Alamat pertama penimbal tempat mesej yang diterima disimpan msgsz
: Saiz maksimum mesej, tidak termasuk jenis mesej ==> hanya saiz( Msgbuf.mtext), tidak boleh saiz(Msgbuf)
: Jenis mesej
: Benderakan untuk dihantar, lalai kepada 0
msqid :消息队列的ID,由msgget() 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指向的结构体中 本文介绍了Linux系统中System V 消息队列的方法,包括消息队列的创建、打开、发送、接收、关闭和删除等方面。通过了解和掌握这些知识,我们可以更好地使用System V 消息队列来实现进程间通信,提高系统的稳定性和效率。当然,Linux系统中System V 消息队列还有很多其他的特性和用法,需要我们不断地学习和研究。希望本文能给你带来一些启发和帮助。 Atas ialah kandungan terperinci Barisan Mesej Linux IPC System V: Cara Klasik untuk Penghantaran Mesej Boleh Dipercayai. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!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);
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 */
};
//_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;
}