Mengapa panjang jalur soket terbatas hingga seratus karakter?

18

Pada sistem Unix nama jalur biasanya hampir tidak memiliki batasan panjang (well, 4096 karakter di Linux) ... kecuali untuk jalur file socket yang dibatasi hingga sekitar 100 karakter (107 karakter di Linux ).

  • Pertanyaan pertama: mengapa pembatasan yang begitu rendah?

Saya telah memeriksa bahwa tampaknya mungkin untuk mengatasi keterbatasan ini dengan mengubah direktori kerja saat ini dan membuat di berbagai direktori beberapa file soket semua menggunakan jalur yang sama ./myfile.sock: aplikasi klien tampaknya terhubung dengan benar ke proses server yang diharapkan meskipun lsofmenunjukkan semua dari mereka mendengarkan di jalur file socket yang sama.

  • Apakah solusi ini dapat diandalkan atau apakah saya hanya beruntung?
  • Apakah perilaku ini khusus untuk Linux atau dapatkah solusi ini berlaku untuk Unix lain juga?
WhiteWinterWolf
sumber
Batasnya bahkan lebih rendah (104) pada sistem OpenBSD saat ini atau Mac OS X 10.11.
tangkap
Yang penting, itu harus lebih rendah dari 108, demi kompatibilitas :)
AFAIK itu 108 karakter di Linux. Silakan periksa /usr/include/$arch-linux-gnu/sys/un.h di komputer Anda.
schaiba
@schaiba: 108 byte, yang berarti string 107 karakter yang diakhiri dengan terminator nol.
WhiteWinterWolf

Jawaban:

18

Kompatibilitas dengan platform lain, atau kompatibilitas dengan hal-hal lama untuk menghindari overruns saat menggunakan snprintf()dan strncpy().

Michael Kerrisk menjelaskan dalam bukunya di halaman 1165 - Bab 57, Sockets: Unix domain:

SUSv3 tidak menentukan ukuran bidang sun_path. Implementasi BSD awal menggunakan 108 dan 104 byte, dan satu implementasi kontemporer (HP-UX 11) menggunakan 92 byte. Aplikasi portabel harus memberi kode pada nilai yang lebih rendah ini, dan menggunakan snprintf () atau strncpy () untuk menghindari buffer berlebih saat menulis ke dalam bidang ini.

Orang-orang Docker bahkan menertawakannya, karena beberapa soket panjangnya 110 karakter:

Inilah sebabnya mengapa LINUX menggunakan soket 108 char. Bisakah ini diubah? Tentu saja. Dan ini, adalah alasan mengapa pembatasan ini dibuat pada Sistem Operasi yang lebih lama:

Mengutip jawabannya:

Itu untuk mencocokkan ruang yang tersedia dalam struktur data kernel yang berguna.

Mengutip "Desain dan Implementasi Sistem Operasi 4.4BSD" oleh McKusick et. Al. (halaman 369):

Fasilitas manajemen memori berputar di sekitar struktur data yang disebut mbuf. Mbuf, atau buffer memori, berukuran 128 byte, dengan 100 atau 108 byte ruang ini disediakan untuk penyimpanan data.

OS lain (unix domain sockets):


sumber
1
SUSv3 XNET diam karena tidak ada konsensus tentang masalah ini.
fpmurphy
Apakah Anda memiliki tautan untuk membuktikan sudut pandang Anda?
Terima kasih atas jawaban ini. Apakah dapat diandalkan untuk menggunakan beberapa file soket yang memiliki nama yang identik relatif terhadap direktori kerja yang berbeda (misalnya, membuat file soket bernama ./my.socketdirektori di bawah ini A/, dan file soket lainnya juga bernama di ./my.socketbawah direktori B/)? lsoftidak membuat perbedaan antara dua file socket, namun sepertinya masih berfungsi tetapi saya bertanya-tanya apakah ini hanya karena saya beruntung. Ini akan menjadi solusi yang baik untuk membuat file socket di bawah jalur yang sudah lebih panjang dari ukuran yang diizinkan.
WhiteWinterWolf
Mencari soket unix di server surat saya, sepertinya membawa nama path lengkap: lsof -U| grep amavis(baris baru)amavis-se 2708 zimbra 17u unix 0xffff8806c0a95400 0t0 310330411 /opt/zimbra/data/tmp/amavisd-zmq.sock
Ya, saya tahu ini tidak biasa, maka pertanyaan saya di sini;)! Untuk apa yang saya uji, nama relatif berfungsi, tetapi masih terasa aneh bagi saya ... tetapi berhasil. Aplikasi saya tidak mencakup seluruh sistem, jadi file socket disimpan dengan semua data aplikasi lain di lokasi yang dikontrol pengguna, yang sangat disukai tetapi dengan jalur yang berpotensi terlalu panjang, atau saya dapat mengacaukan /tmpdengan berton-ton direktori undeleted unik yang masing-masing berisi file soket tunggal (benar-benar jelek, tetapi portabel dan aman).
WhiteWinterWolf
5

Mengenai alasannya, nwildner sudah menulis jawaban yang bagus .

Di sini saya hanya akan fokus pada bagaimana dan penggunaan jalur relatif.

Secara internal, sementara file socket juga dapat dicari berdasarkan nama (saya kira), mereka biasanya dicari oleh inode. Di Linux, pencarian ini dijamin oleh fungsi yang unix_find_socket_byinode()didefinisikan dalam net / unix / af_unix.c .

Ini dapat dengan mudah diperiksa sebagai berikut:

  • Buat dua direktori A / dan B / .
  • Di bawah setiap direktori, buat proses mendengarkan pada file socket bertuliskan nama yang sama. Dengan socatAnda akan menggunakan perintah seperti:
$ socat UNIX-LISTEN:./my.sock -
  • Sekarang tukar file socket dengan memindahkan A / my.sock ke B / dan sebaliknya.
  • Mulai sekarang, jika aplikasi klien terhubung ke A / my.sock, ia akan menghubungi server B , dan jika itu terhubung ke B / my.sock, itu akan menghubungi server A (perhatikan bahwa ketika komunikasi berakhir, proses server mungkin hapus dengan sah apa yang dianggapnya sebagai file soketnya sendiri).

Saya memeriksa perilaku ini pada beberapa sistem Unix (Linux Debian, FreeBSD dan OpenIndiana untuk mendapatkan keragaman), jadi perilaku ini setidaknya menyebar luas, jika tidak standar.

Path absolut biasanya digunakan sebagai konvensi antara klien dan proses server, karena proses klien mungkin tidak tahu bagaimana membangun komunikasi awal dengan server.

Namun, jika komunikasi awal ini tidak menjadi masalah, maka dari itu tampaknya aman untuk menggunakan jalur relatif untuk pembuatan file socket, memungkinkan untuk menghindari masalah panjang jalur ketika lokasi file soket tidak secara langsung dikendalikan oleh proses server.

WhiteWinterWolf
sumber