โครงสร้างซ็อกเก็ตเคอร์เนลและ TCP_DIAG


18

ฉันกำลังทำงานกับซอฟต์แวร์ที่เชื่อมต่อกับเซิร์ฟเวอร์ข้อมูลแบบเรียลไทม์ (โดยใช้ TCP) และฉันมีการเชื่อมต่อลดลง ฉันเดาว่าลูกค้าไม่อ่านข้อมูลที่มาจากเซิร์ฟเวอร์เร็วพอ ดังนั้นฉันต้องการตรวจสอบซ็อกเก็ต TCP ของฉัน สำหรับสิ่งนี้ฉันพบเครื่องมือ "ss"

เครื่องมือนี้อนุญาตให้เห็นสถานะของซ็อกเก็ตทุกอัน - นี่คือตัวอย่างบรรทัดของเอาต์พุตของคำสั่ง ss -inm 'src *:50000'

ESTAB      0      0             184.7.60.2:50000       184.92.35.104:1105
  mem:(r0,w0,f0,t0) sack rto:204 rtt:1.875/0.75 ato:40

คำถามของฉันคืออะไรส่วนความจำหมายถึงอะไร ดูที่ซอร์สโค้ดของเครื่องมือฉันพบว่าข้อมูลมาจากโครงสร้างเคอร์เนล ( sockในsock.h) แม่นยำยิ่งขึ้นมันมาจากฟิลด์:

r = sk->sk_rmem_alloc
w = sk->sk_wmem_queued;
f = sk->sk_forward_alloc;
t = sk->sk_wmem_alloc;

มีใครรู้บ้างว่าพวกเขาหมายถึงอะไร? ฉันเดาว่า:

  • rmem_alloc : ขนาดของบัฟเฟอร์ขาเข้า
  • wmem_alloc : ขนาดของบัฟเฟอร์ขาออก
  • sk_forward_alloc : ???
  • sk->sk_wmem_queued : ???

นี่คือขนาดบัฟเฟอร์ของฉัน:

net.ipv4.tcp_rmem = 4096        87380   174760
net.ipv4.tcp_wmem = 4096        16384   131072
net.ipv4.tcp_mem = 786432       1048576 1572864
net.core.rmem_default = 110592
net.core.wmem_default = 110592
net.core.rmem_max = 1048576
net.core.wmem_max = 131071

การกำหนดค่าขนาดบัฟเฟอร์ของคุณคืออะไร คุณเห็นได้รับบัฟเฟอร์ที่อิ่มตัวในการเชื่อมต่อซ็อกเก็ต? พรรคของคุณปล่อยการเชื่อมต่อกับ EWOULDBLOCK หรือไม่?
Karlson

ขนาดซ็อกเก็ตของฉันมีขนาดค่อนข้างเล็กฉันคิดว่าฉันอัพเดตโพสต์ด้วย สำหรับ EWOULDBLOCK ฉันไม่สามารถบอกได้ ลูกค้าของฉันอยู่ใน JAVA และเพิ่งบอกว่าเซิร์ฟเวอร์ถูกตัดการเชื่อมต่อแล้ว เซิร์ฟเวอร์อยู่ใน C ++ และเพิ่งบอกว่าเขาเลิกการเชื่อมต่อโดยไม่มีข้อมูลใด ๆ ฉันไม่มีซอร์สโค้ดของเซิร์ฟเวอร์ดังนั้นฉันจึงไม่สามารถเปลี่ยนพฤติกรรมได้ ดูเหมือนว่าลูกค้าจะถูกตัดการเชื่อมต่อเมื่อโอเวอร์โหลดเล็กน้อยแม้ว่าจะใช้เวลาเพียงไม่กี่วินาทีเท่านั้นก็ตาม
Twister

การกำหนดค่าขนาดบัฟเฟอร์สามารถปรับได้บนเซิร์ฟเวอร์หรือไม่? คุณสามารถดูขนาดบัฟเฟอร์บนไคลเอนต์ได้หรือไม่? คุณมีการเข้าถึงแหล่งที่มาของลูกค้าหรือไม่? คุณรัน netstat -apnc เพื่อดูขนาดบัฟเฟอร์หรือไม่? คุณพยายามเพิ่มขนาดบัฟเฟอร์ในเคอร์เนลเพื่อดูว่าเกิดอะไรขึ้น
Karlson

ใช่แล้วและถูกตั้งค่าเป็นค่าสูงสุดของเซิร์ฟเวอร์แล้ว (ฉันเชื่อว่ามันไม่สามารถมีขนาดใหญ่กว่าคุณสมบัติ net.ipv4.tcp_ * ใช่ไหม?) สำหรับ netstat -apnc มันไม่ได้ให้ขนาดบัฟเฟอร์ นั่นเป็นเหตุผลที่ฉันดูที่เอสเอส สำหรับเคอร์เนลฉันไม่ได้รูทบนเซิร์ฟเวอร์และทีมไอทีที่นี่ค่อนข้างดื้อรั้น ฉันต้องแน่ใจว่าเกิดอะไรขึ้นก่อนที่ฉันจะขอให้พวกเขาเปลี่ยนค่า ... และใช่ฉันมีสิทธิ์เข้าถึงแหล่งลูกค้าและการตรวจสอบลูกค้ายืนยันว่าการตัดการเชื่อมต่อมาจากเซิร์ฟเวอร์
Twister

netstat -apnc ให้ขนาดทั้งหมดของการส่งและรับคิวบน Linux หากเซิร์ฟเวอร์ตั้งค่าบัฟเฟอร์ให้สูงสุดที่มีอยู่และคุณยังคงอิ่มตัวอยู่คุณอาจต้องการการตั้งค่าบัฟเฟอร์ที่สูงกว่าในระดับระบบปฏิบัติการ
Karlson

คำตอบ:


7

sk_forward_alloc คือหน่วยความจำที่จัดสรรไว้ล่วงหน้าซึ่งเป็นหน่วยความจำทั้งหมดที่มีอยู่ในโควต้าของซ็อกเก็ต

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

คุณสามารถเรียนรู้เพิ่มเติมเกี่ยวกับการจัดการหน่วยความจำ TCP ในบทที่ 9 ของสถาปัตยกรรม TCP / IP การออกแบบและการนำไปใช้ใน Linux โดย Sameer Seth, M. Ajaykumar Venkatesulu


ฉันไม่เข้าใจว่าคำจำกัดความของคำนี้sk_wmem_queuedแตกต่างจากsk_wmem_allocนี้คุณช่วยขยายความเล็กน้อยลงไปได้ไหม? (ถ้าคุณรู้คำตอบอย่าลังเลที่จะเพิ่มคำตอบสำหรับคำถามนี้: unix.stackexchange.com/questions/551444/… )
little-dude

1

ดูหน้าคนของเอสเอส

<fwd_alloc>
   The  memory allocated by the socket as cache, but not used for receiving/sending packet yet. If need memory to send/receive packet, the memory in this cache will be used before allocate additional memory.

<wmem_queued>
   The memory allocated for sending packet (which has not been sent to layer 3)

0

เกี่ยวกับsk_wmem_queuedและsk_wmem_allocฉันถามคำถามเดียวกันดังนั้นฉันจะคัดลอกคำตอบที่นี่:

ฉันส่งอีเมล Eric Dumazet ซึ่งเป็นผู้สนับสนุนกองเครือข่าย Linux และนี่คือคำตอบ:

sk_wmem_allocติดตามจำนวนไบต์สำหรับ skb เข้าคิวหลังจาก transport stack: qdisc layer และบัฟเฟอร์วงแหวน NIC TX

หากคุณมีข้อมูลอยู่ในคิวการเขียน TCP 1 MB ซึ่งยังไม่ได้ส่ง (ขีด จำกัด cwnd) sk_wmem_queueจะมีขนาดประมาณ 1MB แต่sk_wmem_allocจะอยู่ที่ประมาณ 0

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

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

ดังนั้นโดยทั่วไป: sk_wmem_queuesเป็นหน่วยความจำที่ใช้โดยบัฟเฟอร์ซ็อกเก็ต ( sock.sk_write_queue) ในขณะsk_wmem_allocที่หน่วยความจำที่ใช้โดยแพ็กเก็ตในคิวคิวและอุปกรณ์คิว

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