FIFO Programming

Named Pipes

ไปป์ระบุชื่อ (Named Pipes - FIFOs)

FIFO หรือย่อมาจาก "First In, First Out" (อ่านว่า Fy-Foh) ในอีกชื่อหนึ่งก็คือ named pipe ซึ่งหมายถึง pipe ที่มีชื่อไฟล์ของตัวเอง โดยตัว named pipe นี้จะเหมือน pipe ทั่วไปยกเว้นมันสามารถถูกตั้งชื่อได้ ซึ่งจะมีข้อดีคือสามารถระบุ pipe ได้และโปรเซสอื่นๆก็สามารถเรียกใช้ได้ง่ายขึ้นซึ่งจะคล้ายกับการเปิดไฟล์ทั่วไปด้วยคำสั่ง open() ดังนั้นก่อนที่จะใช้ named pipe (FIFO) จะต้องใช้คำสั่ง mknod() เพื่อสร้างไฟล์ชนิดนี้เป็นอย่างแรก ดังตัวอย่างข้างล่างนี้

mknod("myfifo", S_IFIFO | 0644 , 0);

จากตัวอย่างข้างล่างนี้ตัวไฟล์ FIFO ถูกตั้งชื่อว่า myfifo นอกจากนั้นจะมีการกำหนดค่าอาร์กิวเม้นต์เพื่อระบุโหมดของไฟล์เช่น S_IFIFO | 0644 ซึ่งเป็นการระบุว่าเป็นไฟล์ FIFO และมีสิทธิ์การเข้าถึง (access permission) เป็น 644 (เลขฐานแปด) หรือเทียบเท่ากับ rw-r--r-- ซึ่งรายละเอียดของโหมดนั้นจะถูกเก็บอยู่ในไฟล์ sys/stat.h ในอีกทางหนึ่งสามารถสร้างไฟล์ FIFO ได้ด้วยคำสั่ง mknod หรือ mkfifo ดังข้างล่างนี้

$ mknod myfifo p
$ chmod 0644 myfifo 
$ ls -al myfifo
prw-r--r-- 1 wiroon wiroon 0 Sep 18 14:06 myfifo

โดยที่ p เป็นตัวระบุให้เป็นไฟล์ชนิด pipe หรืออาจจะใช้คำสั่ง mkfifo ดังตัวอย่างข้างล่างนี้

$ mkfifo -m 0644 myfifo
$ ls -al myfifo
prw-r--r-- 1 wiroon wiroon 0 Sep 18 14:06 myfifo

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

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

  • ฟังก์ชัน int mkfifo(char *path, mode_t mode)

    • โดยที่ตัวแปรพอยเตอร์ path จะหมายถึงไฟล์ FIFO ที่ต้องการจะสร้างขึ้น และตัวแปร mode จะหมายถึงการระบุสิทธิ์การเข้าถึง (ดูเพิ่มได้จากคำสั่ง unmask และ chmod ซึ่งจะส่งค่ากลับที่ไม่เท่ากับศูนย์ในกรณีที่ไม่มีความผิดพลาดขณะสร้างไฟล์

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

แสดงตัวอย่างโปรแกรมสำหรับทดสอบการส่งข้อมูลผ่านไฟล์ FIFO ดังแสดงข้างล่างนี้

โดยมีขั้นตอนการสร้างไฟล์ FIFO และส่งข้อมูลผ่านไฟล์ FIFO ไปยังโปรแกรม nampipes โดยมีขั้นตอนดังนี้

เมื่อกลับมาดูหน้าต่าง Terminal 1 จะแสดงผลดังแสดงข้างล่างนี<หน้าต่างที่ 1>

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

แสดงตัวอย่างการสร้าง name pipe ด้วยการเรียกฟังก์ชัน mkfifo() ตาม path ที่กำหนดคือ /tmp/AtoB โดยโปรเซสแม่ จะทำการสร้างโปรเซสลูกขึ้นมา เพื่อให้โปรเซสลูกเป็นผู้เขียนข้อมูล (writer) เท่านั้น (O_WRONLY) แล้วโปรเซสแม่จะเป็นผู้อ่านข้อมูล (reader) เท่านั้น (O_RDONLY)ซึ่งโปรเซสลูกจะทำการคอยด้วยฟังก์ชัน wait(NULL); จนกว่าโปรเซสแม่ได้รับข้อมูลครบจึงจะลบ named pip ออกด้วยฟังก์ชัน unlink();

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

แสดงตัวอย่างการดำเนินการทำงานในลักษณะของ FIFO โดยการสร้างไฟล์ pipe ในลักษณะไฟล์สตรีม (file stream) โดยใช้ฟังก์ชัน fopen() และ fclose() ซึ่งแตกต่างจากคำสั่ง open() เนื่องจากคำสั่ง open() นี้จะต้องมีการสร้างไฟล์ pipe ที่มีอยู่จริงๆบนระบบไฟล์ภายในฮาร์ดดิสของระบบ แต่ในขณะที่คำสั่ง fopen() จะเป็นการสร้างไฟล์ pipe อยู่ภายในตัวเคอร์เนลของระบบปฏิบัติการลีนุกซ์ ดังตัวอย่างข้างล่างนี้

สร้างโปรแกรมที่ทำตัวเองเป็น server โดยการเปิดไฟล์ pipe (MYFIFO) เพื่อรอรับข้อมูล โดยการเปิดอ่านไฟล์ pipe ที่ถูกสร้างขึ้นในเคอร์เนล ดังตัวอย่างข้างล่างนี้

ทำการคอมไพล์โปรแกรม และรันโปรแกรม ซึ่งการทำงานของ FIFO นั้นจะทำงานรออยู่ตลอดเวลา

สร้างโปรแกรมที่ทำหน้าที่ส่งข้อมูลไปยังโปรแกรม fifoserver1 โดยการส่งผ่าน (write) ไฟล์ pipe ชื่อ MYFIFO ที่ถูกเปิดรออยู่แล้วในเคอร์เนล ดังตัวอย่างข้างล่างนี้

ทำการคอมไพล์โปรแกรมและรันโปรแกรมเพื่อทำการส่งข้อความ "Hello from FIFO Client" ไปยังโปรแกรม fifoserver1 โดยการทำงานของ FIFO นั้นจะทำงานรออยู่ตลอดเวลา

ดังนั้นเมื่อมองกลับมาที่หน้าต่าง Terminal ที่ 1 ก็จะเห็นข้อมูลที่ตัวโปรแกรม fifoserver1 ได้รับมาจากไฟล์ pipe (MYFIFO) ดังแสดงข้างล่างนี้

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

แสดงตัวอย่างการประยุกต์ให้รองรับ multi-client แล้วตัว server จะส่งข้อความกลับไปยัง client ตัวนั้นๆผ่านไฟล์ MYFIFO2 ดังไฟล์ server แสดงข้างล่างนี้

ไฟล์ fifo client ดังแสดงข้างล่าง

เมื่อกลับมาดูหน้าต่าง Terminal 1 จะแสดงผลดังแสดงข้างล่างนี้<หน้าต่างที่ 1>

Last updated

Was this helpful?