เหตุใดความยาวเส้นทางซ็อกเก็ตจึง จำกัด เพียงหนึ่งร้อยตัวอักษร


18

บนชื่อพา ธ ของระบบ Unix มักจะไม่จำกัดความยาว (เช่น 4096 ตัวอักษรบน Linux) ... ยกเว้นเส้นทางของไฟล์ซ็อกเก็ตซึ่ง จำกัด อยู่ที่ประมาณ 100 ตัวอักษร (107 ตัวอักษรบนLinux )

  • คำถามแรก: ทำไมถึงมีข้อ จำกัด ต่ำ

ผมได้ตรวจสอบว่ามันดูเหมือนเป็นไปได้ที่จะหลีกเลี่ยงข้อ จำกัด นี้โดยการเปลี่ยนไดเรกทอรีการทำงานปัจจุบันและการสร้างในไดเรกทอรีต่างๆหลายซ็อกเก็ตไฟล์ทั้งหมดที่ใช้เส้นทางเดียวกัน./myfile.sock: ใช้งานของลูกค้าดูเหมือนจะถูกต้องเชื่อมต่อกับเซิร์ฟเวอร์กระบวนการคาดว่าแม้แม้ว่าlsofการแสดงทั้งหมด ของพวกเขาฟังบนเส้นทางไฟล์ซ็อกเก็ตเดียวกัน

  • วิธีนี้เป็นวิธีที่เชื่อถือได้หรือฉันแค่โชคดี?
  • พฤติกรรมนี้มีเฉพาะกับ Linux หรืออาจใช้วิธีแก้ปัญหานี้กับ Unixes อื่นเช่นกัน?

ขีด จำกัด ต่ำกว่า (104) สำหรับระบบ OpenBSD ปัจจุบันหรือ Mac OS X 10.11
thrig

สิ่งสำคัญคือจะต้องต่ำกว่า 108 เพื่อความเข้ากันได้ :)

AFAIK เป็น 108 ตัวอักษรบน Linux โปรดตรวจสอบ /usr/include/$arch-linux-gnu/sys/un.h บนเครื่องของคุณ
schaiba

@schaiba: 108 ไบต์ซึ่งหมายถึงสตริงอักขระ 107 ตัวที่ลงท้ายด้วยตัวปิดเทอร์มินัล null
WhiteWinterWolf

คำตอบ:


18

ความเข้ากันได้กับแพลตฟอร์มอื่น ๆ หรือความเข้ากันได้กับสิ่งเก่าเพื่อหลีกเลี่ยงการรุกในขณะที่ใช้และsnprintf()strncpy()

Michael Kerrisk อธิบายในหนังสือของเขาที่หน้า 1165 - บทที่ 57, ซ็อกเก็ต: โดเมน Unix:

SUSv3 ไม่ได้ระบุขนาดของฟิลด์ sun_path การใช้ BSD ก่อนหน้านี้ใช้ 108 และ 104 ไบต์และหนึ่งการติดตั้งในปัจจุบัน (HP-UX 11) ใช้ 92 ไบต์ แอปพลิเคชั่นแบบพกพาควรเขียนโค้ดให้มีค่าต่ำกว่านี้และใช้ snprintf () หรือ strncpy () เพื่อหลีกเลี่ยงบัฟเฟอร์โอเวอร์รันเมื่อเขียนลงในฟิลด์นี้

พวกนักเทียบท่ายังสนุกกับมันเพราะซ็อกเก็ตบางอันมีความยาว 110 ตัวอักษร:

นี่คือเหตุผลที่ LINUX ใช้ซ็อกเก็ต 108 ถ่าน สิ่งนี้สามารถเปลี่ยนแปลงได้? แน่นอน. และนี่คือเหตุผลว่าทำไมข้อ จำกัด นี้จึงถูกสร้างขึ้นในระบบปฏิบัติการรุ่นเก่า:

อ้างคำตอบ:

มันคือการจับคู่พื้นที่ว่างที่มีอยู่ในโครงสร้างข้อมูลเคอร์เนลที่มีประโยชน์

ข้อความ "การออกแบบและการใช้งานระบบปฏิบัติการ 4.4BSD" โดย McKusick และ อัล (หน้า 369):

เครื่องมือจัดการหน่วยความจำจะหมุนรอบโครงสร้างข้อมูลที่เรียกว่า mbuf Mbufs หรือบัฟเฟอร์หน่วยความจำมีความยาว 128 ไบต์โดย 100 หรือ 108 ไบต์ของพื้นที่นี้สงวนไว้สำหรับการจัดเก็บข้อมูล

ระบบปฏิบัติการอื่น ๆ (ซ็อกเก็ตโดเมน unix):


1
SUSv3 XNET เงียบเพราะไม่มีข้อสรุปเกี่ยวกับปัญหา
fpmurphy

คุณมีลิงค์ใด ๆ เพื่อพิสูจน์มุมมองของคุณหรือไม่?

ขอบคุณสำหรับคำตอบนี้ มันเป็นความน่าเชื่อถือในการใช้ไฟล์ซ็อกเก็ตหลายแบกชื่อเหมือนญาติไปยังไดเรกทอรีการทำงานที่แตกต่างกัน (เช่นสร้างไฟล์ซ็อกเก็ตชื่อ./my.socketดังต่อไปนี้ไดเรกทอรีA/และไฟล์อื่นซ็อกเก็ตชื่อ./my.socketดังต่อไปนี้ไดเรกทอรีB/)? lsofไม่ได้แยกแยะความแตกต่างระหว่างไฟล์ซ็อกเก็ตสองไฟล์อย่างไรก็ตามมันยังคงใช้งานได้ แต่ฉันสงสัยว่านี่เป็นเพียงเพราะฉันโชคดี นี่จะเป็นวิธีแก้ปัญหาที่ดีในการสร้างไฟล์ซ็อกเก็ตด้านล่างเส้นทางซึ่งมีขนาดยาวกว่าขนาดที่อนุญาตแล้ว
WhiteWinterWolf

ค้นหาซ็อกเก็ตยูนิกซ์ในเซิร์ฟเวอร์อีเมลของฉันดูเหมือนว่าจะนำชื่อเส้นทางแบบเต็ม: lsof -U| grep amavis(ขึ้นบรรทัดใหม่)amavis-se 2708 zimbra 17u unix 0xffff8806c0a95400 0t0 310330411 /opt/zimbra/data/tmp/amavisd-zmq.sock

ใช่ฉันรู้ว่ามันผิดปกติดังนั้นคำถามของฉันที่นี่;)! สำหรับสิ่งที่ฉันทดสอบชื่อสัมพัทธ์ใช้งานได้ แต่มันก็ดูแปลกสำหรับฉัน ... แต่มันก็ใช้ได้ ใบสมัครของฉันไม่ได้ทั้งระบบเพื่อให้ไฟล์ซ็อกเก็ตจะถูกเก็บไว้ทั้งที่มีข้อมูลการใช้อื่น ๆ ทั้งหมดในสถานที่ที่ผู้ใช้ควบคุมซึ่งเป็นที่ต้องการอย่างมาก แต่มีเส้นทางที่อาจเกิดขึ้นนานเกินไปหรือฉันสามารถถ่วง/tmpกับตันของไดเรกทอรียกเลิกการลบชื่อที่ไม่ซ้ำกันในแต่ละ มีไฟล์ซ็อกเก็ตเดียว (น่าเกลียดที่สุด แต่พกพาง่ายและปลอดภัย)
WhiteWinterWolf

5

เกี่ยวกับสาเหตุที่ nwildner เขียนคำตอบที่ยอดเยี่ยมแล้ว

ที่นี่ฉันจะมุ่งเน้นไปที่วิธีและการใช้เส้นทางสัมพัทธ์

ภายในขณะที่ไฟล์ซ็อกเก็ตยังสามารถค้นหาตามชื่อ (ฉันเดา) พวกเขามักจะค้นหาโดยไอโหนด ในลินุกซ์, การค้นหานี้คือมั่นใจโดยฟังก์ชั่นunix_find_socket_byinode()ที่กำหนดไว้ในสุทธิ / Unix / af_unix.c

สามารถตรวจสอบได้ง่ายดังนี้

  • สร้างสองไดเรกทอรีA /และB /
  • ภายใต้แต่ละไดเรกทอรีให้กระบวนการฟังไฟล์ซ็อกเก็ตที่มีชื่อเดียวกัน ด้วยsocatคุณจะใช้คำสั่งเช่น:
$ socat UNIX-LISTEN:./my.sock -
  • ตอนนี้แลกเปลี่ยนไฟล์ซ็อกเก็ตโดยการย้ายA / my.sockเป็นB /และในทางกลับกัน
  • จากนี้ไปหากแอปพลิเคชันไคลเอนต์เชื่อมต่อกับA / my.sockมันจะติดต่อกับเซิร์ฟเวอร์Bและถ้ามันเชื่อมต่อกับB / my.sockมันจะติดต่อกับเซิร์ฟเวอร์A (โปรดทราบว่าเมื่อการสื่อสารสิ้นสุดลงกระบวนการเซิร์ฟเวอร์อาจ ลบสิ่งที่คิดว่าเป็นไฟล์ซ็อกเก็ตของตัวเอง)

ฉันตรวจสอบพฤติกรรมนี้ในระบบ Unix จำนวนหนึ่ง (Linux Debian, FreeBSD และ OpenIndiana เพื่อให้ได้ความหลากหลาย) ดังนั้นพฤติกรรมนี้ดูเหมือนจะแพร่กระจายอย่างน้อยถ้าไม่ใช่มาตรฐาน

เส้นทางแบบสัมบูรณ์มักใช้เป็นแบบแผนระหว่างไคลเอ็นต์และกระบวนการเซิร์ฟเวอร์เนื่องจากกระบวนการไคลเอ็นต์อาจไม่ทราบวิธีสร้างการสื่อสารเริ่มต้นกับเซิร์ฟเวอร์

อย่างไรก็ตามหากการสื่อสารเริ่มต้นนี้ไม่เป็นปัญหาดูเหมือนว่าปลอดภัยที่จะใช้พา ธ สัมพัทธ์สำหรับการสร้างไฟล์ซ็อกเก็ตช่วยให้หลีกเลี่ยงปัญหาความยาวพา ธ เมื่อตำแหน่งไฟล์ซ็อกเก็ตไม่ได้ถูกควบคุมโดยตรงโดยกระบวนการเซิร์ฟเวอร์

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