System V

Message Queue based on System V

จะมีลักษณะคล้ายกับไฟล์ pipe คือสามารถส่งบล็อกข้อมูลจากโปรเซสหนึ่งไปยังอีกโปรเซสหนึ่งผ่านลีนุกซ์คอร์เนลเช่นเดียวกัน โดยแต่ละบล็อกข้อมูลจะมีหมายเลขอ้างอิงกำหนดไว้ให้เพื่อให้โปรเซสอื่นๆสามารถอ้างอิงหมายเลขข้อมูลที่ต้องการนั้นได้ ซึ่งจะไม่เหมือนกับการส่งข้อมูลผ่าน pipe ซึ่งทั้งสองโปรเซสจะต้องรอซึ่งกันและกัน ดังนั้นขั้นตอนการส่งข้อมูลแบบ message queue จะมีขั้นตอนคือโปรเซสที่ทำการเขียนข้อมูลไปยัง queue (ด้วยคำสั่ง msgsnd) แล้ว ก็สามารถจบการทำงานได้ทันที ถ้าโปรเซสใดต้องการอ่านก็สามารถเข้าไปอ่านข้อมูลใน queue ได้ภายหลัง (ด้วยคำสั่ง msgrcv) ซึ่งตัว message queue เปรียบเสมือนกล่องส่วนกลางที่จะมีโปรเซสใดก็ได้ที่สามารถเข้ามาทิ้งข้อมูลไว้ หรือจะมีโปรเซสใดก็ได้ที่จะเข้ามาดึงข้อความจากกล่องที่แชร์ไว้นี้ได้

ภายใต้มาตราฐาน System V IPC เมื่อโปรเซสมีการสร้าง message queue แล้ว แม้ว่าโปรเซสนั้นถูกทำลายหรือสิ้นสุดการทำงานไปแล้วก็ตาม แต่ตัว message queue นั้นก็ยังค้างอยู่ในระบบซึ่งสามารถใช้คำสั่ง ipcs ภายใน shell เพื่อแสดงรายการ message queue ที่มีอยู่ในระบบดังตัวอย่างการใช้งานข้างล่างและสามารถใช้คำสั่ง ipcrm เมื่อต้องการลบ message queue ออกไปจากระบบ

$ ipcs -q
------ Message Queues --------
key        msqid      owner       perms      used-bytes   messages    
0x42016dfa 32768      sriborrirux  644        0            0     

ฟังก์ชันและตัวแปรที่เกี่ยวข้อง

  • ไลบรารีที่เกี่ยวข้องคือ sys/types.h, sys/ipc.h และ sys/msg.h

  • ฟังก์ชัน int msgget(key_t key, int msgflg);

    • เมื่อต้องการติดต่อไปยัง message queue หรือสร้าง message queue ขึ้นมาใหม่ โดยการระบุหมายเลขกุญแจ (key) ซึ่งในกรณีที่มีการสร้าง message queue จะต้องระบุค่าแฟลก (flag) ให่กับตัวแปร msgflg เช่น 0666|IPC_CREAT เพื่อระบุสิทธิ์การเข้าถึงของ message queue ของตัวที่จะถูกสร้างขึ้น

ตัวอย่างเช่น โปรแกรม A ต้องการสร้างกุญแจ เพื่อทำการสร้าง message queue ตัวใหม่ จะมีขั้นตอนดังนี้

...
key = ftok("/home/wiroon/somefile", 'P');
msqid = msgget(key, 0666 | IPC_CREAT);
...

ซึ่งจากคำสั่งข้างต้นก็จะได้ message queue ที่มีสิทธิ์การเข้าถึงเป็น 666 หรือ rw-rw-rw- และหมายเลขเฉพาะของ msqid เพื่อให้โปรเซสอื่นๆอ้างอิงหมายเลขของ message queue ที่ต้องการจะเข้าถึงได้ แต่อย่างไรก็ตามโปรเซสใดก็ตามถ้าต้องการเข้าถึง message queue ที่ถูกสร้างโดยโปรแกรม A ก็จะต้องมีขั้นตอนในการนำกุญแจที่จะสามารถเข้ามาเปิดเอาหมายเลข message queue นั้นได้ ดังนั้น โปรแกรมอื่นๆ จึงจำเป็นต้องใช้พารามิเตอร์ภายในฟังก์ชัน ftok() เดียวกันโปรแกรม A ใช้ แล้วจึงจะได้หมายเงขของ message queue (msqid) โดยใช้คำสั่งภายในดังตัวอย่างโปรแกรมข้างล่างนี้

...
key = ftok("/home/wiroon/somefile", 'P');
msqid = msgget(key, 0666);
...

หลังจากสร้างกุญแจและ message queue ได้เรียบร้อยแล้ว แต่อย่างไรก็ตาม message queue ก็ยังมีข้อจำกัดเรื่องขนาดบล็อกข้อมูล ที่จะถูกจำกัดขนาดไว้รวมทั้งจำนวนบล็อกทั้งหมดที่มีบนระบบก็จะถูกจำกัดไว้เช่นกัน ซึ่งภายในระบบปฏิบัติการลีนุกซ์ตัวแปรบล็อกข้อมูลจะประกอบไปด้วย 2 ส่วนคือ MSGMAX(4096) และ MSGMNB(16384) ซึ่งตัวแรกจะหมายถึงความจุของแต่ละบล็อกข้อความ และตัวที่สองจะหมายถึงความจุทั้งหมดของ queue แต่ในบางระบบ ค่าเหล่านี้อาจจะแตกต่างกันไป หรืออาจจะไม่ใช้ค่านี้เลยก็เป็นได้

ฟังก์ชันและตัวแปรที่เกี่ยวข้อง

  • ฟังก์ชัน int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

    • เป็นฟังก์ชันสำหรับใช้ส่งข้อความเข้าไปเก็บใน message queue ตามที่ระบุมหายเลขไว้ (msqid) สำหรับตัวพอยเตอร์ *msgp เป็นตัวชี้ไปยังข้อมูลที่ต้องการนำไปวางบน message queue ตามขนาดไบต์ข้อมูลที่ระบุไว้ (msgsz) นอกจากนั้นก็สามารถกำหนดค่าแฟลกในตัวแปร msgflg ได้เช่นกัน แต่โดยทั่วไปจะกำหนดไว้ในเป็นศูนย์

ในทางปฏิบัติการสร้างข้อมูลเพื่อนำไปเก็บไว้ใน message queue จะมีการสร้างให้อยู่ในลักษณะตัวแปรแบบ struct เช่น

ซึ่งสังเกตว่าจะมีการกำหนดตัวแปร mtype ที่เป็นชนิด long ไว้เริ่มต้นเสมอ ตามคำแนะนำของการใช้งาน message queue ดังนั้นเมื่อต้องหาขนาดของข้อมูลที่แท้จริง จำเป็นจะต้องลบด้วยขนาดของตัวแปร mtype ก่อนเสมอ เช่น

ฟังก์ชันและตัวแปรที่เกี่ยวข้อง

  • ฟังก์ชัน int msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

    • เป็นฟังก์ชันสำหรับอ่านข้อมูลจาก message ลงในตัวแปรพอยเตอร์ *msgp ที่ชี้ไปที่ข้อมูลที่ได้รับมา ดังตัวอย่างข้างล่างนี้

  • ฟังก์ชัน int msgctl(int msqid, int cmd, struct msqid_ds *buf);

    • เป็นฟังก์ชันสำหรับใช้ในควบคุม message queue หมายเลขที่ต้องการ (msqid) โดยการระบุคำสั่ง (cmd) ที่ต้องการเช่น IPC_RMID เพื่อต้องการลบ queue เป็นต้น ทิ้งออกจากระบบ นอกจากจะใช้คำสั่ง ipcrm ที่เคยอธิบายไว้ข้างบน ซึ่งในกรณีที่ใช้ IPC_RMID ก็สามารถระบุค่า NULL ให้กับตัวแปร *buf ได้

แสดงการส่งข้อมูลแบบ message queue

ตัวอย่างที่ 1

แสดงตัวอย่างโปรแกรมสำหรับส่งบล๊อกข้อมูลเข้าไปใน Message Queues โดยสร้างโปรแกรมส่งข้อมูลไปเก็บไว้ใน message queue ชื่อว่า msg_sender.c และโปรแกรมสำหรับอ่านค่าจาก message queue ชื่อว่า msg_receiver.c ดังข้างล่างนี้

โปรแกรม msg_receiver.c สำหรับอ่านบล๊อกข้อมูลภายใน Message Queues ที่โปรแกรม msg_sender.c เขียนข้อมูลเข้าไป

ทำการคอมไพล์โปรแกรม msg_sender แล้วรันโปรแกรมเพื่อพร้อมเขียนข้อมูลลง message queue ต่อไป

กลับมาที่ หน้าต่าง Terminal ที่ 1 เพื่อทำการพิมพ์ข้อความเพื่อส่งไปยัง msg_receiver ดังตังอย่างข่างล่าง

หน้าต่าง Terminal ที่ 1

จะสังเกตุเห็นข้อความปรากฏขึ้นในหน้าต่าง Terminal ที่ 2 เนื่องจากโปรเซส msg_receiver ได้รับแล้วแสดงดังนี้

หน้าต่าง Terminal ที่ 2

Last updated

Was this helpful?