Linux ล้างข้อมูลซ็อกเก็ตโดเมนนามธรรมโดยอัตโนมัติหรือไม่


15

มีคำตอบที่ดีเกี่ยวกับ StackOverflow เกี่ยวกับการมอบการล็อกที่ดีกว่าสำหรับ daemons (สังเคราะห์จากEduardo Fleury ) ที่ไม่ได้ขึ้นอยู่กับกลไกการล็อคไฟล์ PID ทั่วไปสำหรับ daemons มีความคิดเห็นที่ดีมากมายเกี่ยวกับสาเหตุที่ไฟล์ PID ล็อกบางครั้งอาจทำให้เกิดปัญหาดังนั้นฉันจะไม่ทำใหม่ที่นี่

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

แต่ฉันไม่สามารถหาเอกสารที่ชัดเจนใน Linux ที่บอกว่า Linux ทำอะไรกับซ็อกเก็ตนามธรรมเมื่อกระบวนการที่ถูกผูกไว้คือ SIGKILL มีใครรู้บ้าง

ใส่อีกวิธีหนึ่งเมื่อซ็อกเก็ตบทคัดย่อให้อิสระที่จะใช้อีกครั้งอย่างแม่นยำ?

ฉันไม่ต้องการแทนที่กลไกไฟล์ PID ด้วยซ็อกเก็ตที่เป็นนามธรรมเว้นแต่จะแก้ไขปัญหาได้อย่างแน่นอน


3
ฉันไม่พบสิ่งใดที่ตอบคำถามนี้โดยตรง แต่เนื่องจากไม่มี API สำหรับการลบซ็อกเก็ตนามธรรมดูเหมือนว่าพวกเขาจะต้องได้รับการจัดการโดยอัตโนมัติโดยเคอร์เนล เมื่อไม่มีกระบวนการที่ซ็อกเก็ตเปิดมันควรจะหายไป
Barmar

@Barmar ยุติธรรมเพียงพอ สนใจที่จะเพิ่มเป็นคำตอบหรือไม่?
CivFan

ฉันต้องการที่จะมีข้อมูลที่ชัดเจนมากขึ้น
Barmar

คำตอบ:


5

ใช่ linux "ล้าง" ซ็อกเก็ตนามธรรมโดยอัตโนมัติในระดับที่การทำความสะอาดแม้จะสมเหตุสมผล นี่คือตัวอย่างการทำงานขั้นต่ำที่คุณสามารถยืนยันได้:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>

int
main(int argc, char **argv)
{
  int s;
  struct sockaddr_un sun;

  if (argc != 2 || strlen(argv[1]) + 1 > sizeof(sun.sun_path)) {
    fprintf(stderr, "usage: %s abstract-path\n", argv[0]);
    exit(1);
  }

  s = socket(AF_UNIX, SOCK_STREAM, 0);
  if (s < 0) {
    perror("socket");
    exit(1);
  }
  memset(&sun, 0, sizeof(sun));
  sun.sun_family = AF_UNIX;
  strcpy(sun.sun_path + 1, argv[1]);
  if (bind(s, (struct sockaddr *) &sun, sizeof(sun))) {
    perror("bind");
    exit(1);
  }
  pause();
}

เรียกใช้โปรแกรมนี้เป็น./a.out /test-socket &แล้วเรียกใช้แล้วss -ax | grep test-socketคุณจะเห็นซ็อกเก็ตที่ใช้งานอยู่ จากนั้นkill %./a.outและss -axจะแสดงซ็อกเก็ตหายไป

อย่างไรก็ตามเหตุผลที่คุณไม่สามารถล้างข้อมูลนี้ในเอกสารใด ๆ ก็คือมันไม่ได้ทำความสะอาดในลักษณะเดียวกับที่ซ็อกเก็ต unix โดเมนที่ไม่เป็นนามธรรมต้องล้าง ซ็อกเก็ตที่ไม่เป็นนามธรรมจัดสรรไอโหนดและสร้างรายการในไดเรกทอรีซึ่งจำเป็นต้องล้างข้อมูลในระบบไฟล์พื้นฐาน ในทางตรงกันข้ามลองนึกถึงซ็อกเก็ตที่เป็นนามธรรมมากกว่าหมายเลขพอร์ต TCP หรือ UDP แน่นอนถ้าคุณผูกพอร์ต TCP แล้วออกพอร์ต TCP นั้นจะว่างอีกครั้ง แต่สิ่งที่คุณใช้เลข 16 บิตยังคงมีอยู่นามธรรมและทำเสมอ เนมสเปซของหมายเลขพอร์ตคือ 1-65535 และไม่เคยเปลี่ยนแปลงหรือจำเป็นต้องทำความสะอาด

ดังนั้นลองนึกถึงชื่อซ็อกเก็ตแบบนามธรรมเช่นหมายเลขพอร์ต TCP หรือ UDP เพียงเลือกจากชุดหมายเลขพอร์ตที่เป็นไปได้ที่มีขนาดใหญ่กว่าซึ่งดูเหมือนว่าชื่อพา ธ แต่ไม่ใช่ คุณไม่สามารถผูกหมายเลขพอร์ตเดียวกันได้สองครั้ง (ยกเว้นSO_REUSEADDRหรือSO_REUSEPORT) แต่การปิดซ็อกเก็ต (โดยชัดแจ้งหรือโดยปริยายโดยการยกเลิก) ทำให้พอร์ตไม่มีสิ่งใดเหลือให้ทำความสะอาด


ผ่านการทดสอบเป็ดแล้ว ไม่เป็นไรสำหรับบางสิ่งเช่น python แต่ฉันคาดหวังมากกว่านี้สำหรับฟีเจอร์เคอร์เนลของ Linux ยกตัวอย่างพอร์ต TCP / UDP ของคุณ - มีเอกสารมากมายที่อธิบายอย่างแม่นยำเมื่อสามารถนำพอร์ตกลับมาใช้ใหม่ได้
CivFan

2
และทำไมเอกสารดังกล่าวถึงใช้กับซ็อกเก็ตแบบนามธรรมไม่เท่ากัน คุณมีข้อมูลอ้างอิงหรือไม่? คำถามที่ดีกว่านี้อาจเป็นที่ที่มีการบันทึกข้อมูลแทรกซ้อนที่ซับซ้อนเป็นพิเศษสำหรับซ็อกเก็ต Unix-non-abstract ในระบบของฉันนั่นคือunix (7)ซึ่งบอกว่า "Linux ยังรองรับเนมสเปซที่เป็นนามธรรมซึ่งไม่ขึ้นอยู่กับระบบไฟล์" ดังนั้นสำหรับฉัน "อิสระของระบบไฟล์" ไม่มีความหมายถึงการล้างข้อมูลเฉพาะระบบไฟล์
user3188445

5

ฉันโพสต์คำถามนี้ในช่วงหนึ่งปีที่ผ่านมาและไม่เคยพอใจกับการขาดเอกสารที่ชัดเจน ฉันคิดว่าฉันจะตรวจสอบเอกสารของ Linux อีกครั้งสำหรับการอัปเดตใด ๆ และยินดีที่ได้เห็นสิ่งนี้ :

ซ็อกเก็ตบทคัดย่อ

การอนุญาตให้ใช้ซ็อกเก็ตไม่มีความหมายสำหรับซ็อกเก็ตแบบนามธรรม: กระบวนการ umask (2) ไม่มีผลเมื่อเชื่อมต่อซ็อกเก็ตแบบนามธรรมและการเปลี่ยนความเป็นเจ้าของและการอนุญาตของวัตถุ (ผ่าน fchown (2) และ fchmod (2)) ไม่มีผลกับ การเข้าถึงของซ็อกเก็ต

ซ็อกเก็ตบทคัดย่อจะหายไปโดยอัตโนมัติเมื่อการอ้างอิงที่เปิดไปยังซ็อกเก็ตทั้งหมดถูกปิด

นอกจากนี้อินเตอร์เฟสการเขียนโปรแกรม LinuxโดยMichael Kerriskครอบคลุมคำถาม (cross-posted จากคำตอบอื่น ๆ นี้ ):

57.6 Namespace ของซ็อกเก็ตบทคัดย่อของ Linux

abstract namespace ที่เรียกว่าเป็นคุณสมบัติเฉพาะของ Linux ที่ช่วยให้เราสามารถผูกซ็อกเก็ตโดเมน UNIX กับชื่อโดยไม่มีชื่อนั้นถูกสร้างขึ้นในระบบไฟล์ นี่เป็นข้อได้เปรียบที่อาจเกิดขึ้น:

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

ในการสร้างการเชื่อมโยงแบบนามธรรมเราระบุไบต์แรกของ ฟิลด์sun_pathเป็นไบต์ว่าง (\ 0) [ ... ]

ฉันคิดว่าพร้อมด้วยคำตอบของ @ user3188445 สิ่งนี้จะช่วยเคลียร์คำถามได้อย่างแม่นยำมาก

ที่กล่าวว่ายังคงมีสมมติฐานที่ทำที่นี่กระบวนการที่ SIGKILL จะปิดซ็อกเก็ตที่เปิดอยู่ทั้งหมด ดูเหมือนจะเป็นข้อสันนิษฐานที่สมเหตุสมผล แต่ฉันไม่มีเอกสารที่กำหนดพฤติกรรมดังกล่าว


1
ย่อหน้าสุดท้าย: ซ็อกเก็ตเป็นตัวให้คำอธิบายไฟล์และตัวอธิบายไฟล์ที่เปิดอยู่ทั้งหมดจะถูกปิดเมื่อกระบวนการออกจากกระบวนการ อิ ซ็อกเก็ตเป็นไฟล์เปิดไฟล์ที่เปิดสามารถส่งผ่านได้เช่นสืบทอดโดยกระบวนการลูก ดังนั้นคุณควรโทรไปหา socket ด้วยSOCK_CLOEXECในกรณีที่โค้ดใด ๆ (รวมถึงไลบรารี) fork () + exec () การสร้างกระบวนการลูกพิเศษโดยใช้ fork () โดยไม่มี exec () เป็นเรื่องธรรมดาน้อยกว่า คุณอาจรู้แล้วถ้าคุณทำอย่างนั้น
sourcejedi

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