อะไรคือจุดประสงค์ของอาร์กิวเมนต์แรกในการเลือกการเรียกของระบบ?


25

จาก man select

int select(int nfds, fd_set *readfds, fd_set *writefds,
           fd_set *exceptfds, struct timeval *timeout);

nfds เป็นตัวบอกไฟล์ที่มีหมายเลขสูงสุดในสามชุดใด ๆ บวก 1

วัตถุประสงค์ของการคืออะไรnfdsเมื่อเรามีอยู่แล้วreadfds, writefdsและexceptfdsจากการที่อธิบายไฟล์สามารถกำหนด?


ผมกำลังจะถามในดังนั้น แต่มันรวมศูนย์มากขึ้นที่นี่และC เรียก API ได้รับการพิจารณาในหัวข้อ
phunehehe

คำตอบ:


25

ใน"การเขียนโปรแกรมขั้นสูงในสภาพแวดล้อม UNIX" W. Richard Stevens กล่าวว่าเป็นการเพิ่มประสิทธิภาพ:

ด้วยการระบุตัวอธิบายสูงสุดที่เราสนใจเคอร์เนลสามารถหลีกเลี่ยงการผ่านบิตที่ไม่ได้ใช้หลายร้อยบิตในชุดตัวอธิบายทั้งสามโดยมองหาบิตที่เปิดใช้งาน

(ฉบับที่ 1 หน้า 399)

หากคุณกำลังทำการเขียนโปรแกรมระบบ UNIX ชนิดใด ๆ แนะนำให้ใช้หนังสือ APUE


UPDATE

โดยfd_setทั่วไปแล้วสามารถติดตามตัวอธิบายไฟล์ได้สูงสุด 1024 ตัว

วิธีที่มีประสิทธิภาพที่สุดในการติดตามว่าfdsมีการตั้งค่าไว้ที่ใด0และถูกตั้งค่า1เป็นfd_setบิตเซ็ตดังนั้นแต่ละอันประกอบด้วย 1024 บิต

บนระบบ 32 บิต int ที่มีความยาว (หรือ "คำว่า") คือ 32 บิตดังนั้นนั่นหมายความว่าแต่ละคำfd_setคือ
1024/32 = 32 คำ

หากnfdsมีบางสิ่งเล็ก ๆ เช่น 8 หรือ 16 ซึ่งจะมีอยู่ในแอปพลิเคชั่นจำนวนมากจะต้องมองเข้าไปในคำที่ 1 เท่านั้นซึ่งควรจะเร็วกว่าการมองเข้าไปข้างในทั้ง 32

(ดูFD_SETSIZEและ__NFDBITSจาก/usr/include/sys/select.hสำหรับค่าบนแพลตฟอร์มของคุณ)


อัพเดท 2

ว่าทำไมลายเซ็นฟังก์ชั่นไม่ได้

int select(fd_set *readfds, int nreadfds,
           fd_set *writefds, int nwritefds,
           fd_set *exceptfds, int nexceptfds,
           struct timeval *timeout);

ฉันเดาว่าเป็นเพราะรหัสพยายามเก็บอาร์กิวเมนต์ทั้งหมดในการลงทะเบียนเพื่อให้ CPU สามารถทำงานกับพวกเขาได้เร็วขึ้นและหากต้องติดตามตัวแปรเพิ่มเติม 2 ตัว CPU อาจมีการลงทะเบียนไม่เพียงพอ

ดังนั้นในคำอื่น ๆselectคือการเปิดเผยรายละเอียดการดำเนินการเพื่อให้สามารถเร็วขึ้น


2
หรือล่าสุดThe Linux Programming Interface
chris

APUE ได้รับการอัปเดตล่าสุดเช่นกัน รุ่นที่สอง: amazon.com/gp/aw/d.html/ref=aw_d_detail?pd=1&a=0201433079
Mikel

@chris ฉันจะตรวจสอบ Linux Programming Interface ขอบคุณ
มิเคล

ขอบคุณสำหรับข้อมูลฉันจะตรวจสอบหนังสือเมื่อฉันคว้าเวลา
phunehehe

APUE 2nd Ed: 27 มิถุนายน 2548 (ครอบคลุม linux-2.4.22) TLPI: ตุลาคม 2010 (ครอบคลุม linux-2.6.35)
chris

6

ฉันไม่แน่ใจเพราะฉันไม่ใช่หนึ่งในนักออกแบบของ select () แต่ฉันบอกว่ามันเป็นการเพิ่มประสิทธิภาพ ฟังก์ชั่นการโทรรู้จำนวนตัวอธิบายไฟล์ที่ใส่ไว้ในการอ่านเขียนและยกเว้น FDs ดังนั้นทำไมเคอร์เนลจึงควรค้นหาอีกครั้ง

โปรดจำไว้ว่าในช่วงต้นยุค 80 เมื่อมีการเปิดตัว select () พวกเขาไม่มีมัลติโปรเซสเซอร์หลายตัวที่ใช้งานได้ 25 MHz VAX นั้นค่อนข้างเร็วทีเดียว นอกจากนี้คุณต้องการให้ select () ทำงานเร็วขึ้นถ้าทำได้: หาก I / O บางตัวกำลังรอกระบวนการทำไมกระบวนการจึงรอ?


การโต้แย้งของคุณผมจะบอกว่าเราต้องnreadfds, nwritefdsและแทนเพียงอย่างใดอย่างหนึ่งnexceptfds nfds
phunehehe

อาจเป็นไปได้ว่าnfdsจะสามารถลงทะเบียนเพื่อการเข้าถึงที่รวดเร็ว หากต้องติดตามตัวเลขสามตัวพร้อมกับข้อโต้แย้งอื่น ๆ ทั้งหมด CPU อาจมีการลงทะเบียนไม่เพียงพอ แน่นอนเคอร์เนลอาจสร้างขึ้นเองnfdsตามตัวแปรสมมุติ 3 ตัวของคุณ ดังนั้นฉันเดาว่ามันคือการเปิดเผยรายละเอียดการใช้งานเพื่อเพิ่มประสิทธิภาพ
มิเคล

@Mikel, phunehehe: การnfdsโต้แย้งแยกกันจะนำมาซึ่งกำไรที่น้อยมาก FD_SETSIZEมากที่สุดเท่าที่กระบวนการได้เปิดกระบวนการน้อยมากเมื่อเทียบกับ กรณีทั่วไปอาจมี (4,4,2) จาก 1024; การตรวจสอบเคอร์เนล (4,4,4) เป็นการชนะที่ยิ่งใหญ่กว่า (1024,1024,1024) แต่การเพิ่มประสิทธิภาพลงไปที่ (4,4,2) จะไร้ประโยชน์
Gilles 'ดังนั้น - หยุดความชั่วร้าย'

@Gilles: กำไรจะเป็น API ที่สะอาดกว่า (มันเป็นอย่างใดอย่างหนึ่งโปรแกรมที่มีการทำทำงานพิเศษในการคำนวณnfdsหรือจะขี้เกียจและโทรselect(FD_SETSIZE, ...)ซึ่งจะเป็นช้า.)
มิเกล

OTOH การติดตามตัวแปรสูงสุดเพียงตัวเดียวอาจทำให้โปรแกรมเมอร์ง่ายขึ้นเช่นกัน
มิเคล
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.