ทำความเข้าใจไลบรารีที่ใช้ร่วมกันใน Linux
ในการเขียนโปรแกรม ไลบรารีคือชุดของโค้ดที่คอมไพล์ไว้ล่วงหน้าซึ่งสามารถนำมาใช้ซ้ำในโปรแกรมได้ ไลบรารีทำให้ชีวิตของโปรแกรมเมอร์ง่ายขึ้น โดยมีฟังก์ชัน รูทีน คลาส โครงสร้างข้อมูลที่ใช้ซ้ำได้ และอื่นๆ (เขียนโดยโปรแกรมเมอร์คนอื่น) ซึ่งไลบรารีเหล่านั้นสามารถใช้ในโปรแกรมของตนได้
ตัวอย่างเช่น หากคุณกำลังสร้างแอปพลิเคชันที่จำเป็นต้องดำเนินการทางคณิตศาสตร์ คุณไม่จำเป็นต้องสร้างฟังก์ชันทางคณิตศาสตร์ใหม่สำหรับสิ่งนั้น คุณสามารถใช้ฟังก์ชันที่มีอยู่ในไลบรารีสำหรับภาษาการเขียนโปรแกรมนั้นได้
ตัวอย่างของไลบรารีใน Linux ได้แก่ libc (ไลบรารี C มาตรฐาน) หรือ Glibc (ไลบรารี C มาตรฐานเวอร์ชัน GNU), libcurl (ไฟล์ multiprotocol ถ่ายโอนไลบรารี), libcrypt (ไลบรารีที่ใช้สำหรับการเข้ารหัส การแฮช และการเข้ารหัสในภาษา C) และอื่นๆ อีกมากมาย
Linux รองรับไลบรารี่สองคลาส ได้แก่ :
- ไลบรารีแบบคงที่ – เชื่อมโยงกับโปรแกรมแบบคงที่ ณ เวลาคอมไพล์
- ไลบรารีไดนามิกหรือไลบรารีที่ใช้ร่วมกัน – ถูกโหลดเมื่อมีการเรียกใช้โปรแกรมและโหลดลงในหน่วยความจำ และการเชื่อมโยงเกิดขึ้นเมื่อรันไทม์
ไลบรารีแบบไดนามิกหรือแบบแบ่งใช้สามารถแบ่งได้เป็น:
- ไลบรารีที่เชื่อมโยงแบบไดนามิก – ที่นี่โปรแกรมจะเชื่อมโยงกับไลบรารีที่ใช้ร่วมกันและเคอร์เนลจะโหลดไลบรารี (ในกรณีที่ไม่อยู่ในหน่วยความจำ) เมื่อดำเนินการ
- ไลบรารีที่โหลดแบบไดนามิก – โปรแกรมเข้าควบคุมเต็มรูปแบบโดยการเรียกใช้ฟังก์ชันกับไลบรารี
แบบแผนการตั้งชื่อไลบรารีที่ใช้ร่วมกัน
ไลบรารีที่แบ่งใช้มีการตั้งชื่อได้สองวิธี: ชื่อไลบรารี (a.k.a soname) และ “ชื่อไฟล์ ” (พาธสัมบูรณ์ไปยังไฟล์ซึ่งจัดเก็บโค้ดไลบรารี)
ตัวอย่างเช่น soname สำหรับ libc คือ libc.so.6 โดยที่ lib คือคำนำหน้า >c เป็นชื่อที่สื่อความหมาย ดังนั้น หมายถึงวัตถุที่ใช้ร่วมกัน และ 6 คือเวอร์ชัน และชื่อไฟล์คือ: /lib64/libc.so.6 โปรดทราบว่าจริงๆ แล้ว soname เป็นลิงก์สัญลักษณ์ไปยังชื่อไฟล์
การค้นหาไลบรารีที่ใช้ร่วมกันใน Linux
ไลบรารีที่ใช้ร่วมกันถูกโหลดโดย ld.so (หรือ ld.so.x) และ ld-linux.so (หรือ ld- linux.so.x) โดยที่ x คือเวอร์ชัน ใน Linux /lib/ld-linux.so.x จะค้นหาและโหลดไลบรารีที่แบ่งใช้ทั้งหมดที่ใช้โดยโปรแกรม
โปรแกรมสามารถเรียกไลบรารี่โดยใช้ชื่อไลบรารีหรือชื่อไฟล์ และพาธไลบรารีจะเก็บไดเร็กทอรีที่ซึ่งไลบรารีสามารถพบได้ในระบบไฟล์ ตามค่าเริ่มต้น ไลบรารีจะอยู่ใน /usr/local/lib, /usr/local/lib64, /usr/lib และ /usr/lib64; ไลบรารีการเริ่มต้นระบบอยู่ใน /lib และ /lib64 อย่างไรก็ตามโปรแกรมเมอร์สามารถติดตั้งไลบรารี่ในตำแหน่งที่กำหนดเองได้
เส้นทางไลบรารีสามารถกำหนดได้ในไฟล์ /etc/ld.so.conf ซึ่งคุณสามารถแก้ไขได้ด้วยโปรแกรมแก้ไขบรรทัดคำสั่ง
vi /etc/ld.so.conf
บรรทัดในไฟล์นี้แนะนำให้เคอร์เนลโหลดไฟล์ใน /etc/ld.so.conf.d ด้วยวิธีนี้ ผู้ดูแลแพ็คเกจหรือโปรแกรมเมอร์สามารถเพิ่มไดเร็กทอรีไลบรารีแบบกำหนดเองลงในรายการค้นหาได้
หากคุณดูในไดเรกทอรี /etc/ld.so.conf.d คุณจะเห็นไฟล์ .conf สำหรับแพ็คเกจทั่วไปบางแพ็คเกจ (เคอร์เนล, mysql และ postgresql ใน กรณีนี้):
ls /etc/ld.so.conf.d
kernel-2.6.32-358.18.1.el6.x86_64.conf kernel-2.6.32-696.1.1.el6.x86_64.conf mariadb-x86_64.conf
kernel-2.6.32-642.6.2.el6.x86_64.conf kernel-2.6.32-696.6.3.el6.x86_64.conf postgresql-pgdg-libs.conf
หากคุณดูที่ mariadb-x86_64.conf คุณจะเห็นเส้นทางที่แน่นอนไปยังไลบรารีแพ็คเกจ
cat mariadb-x86_64.conf
/usr/lib64/mysql
วิธีการข้างต้นกำหนดเส้นทางไลบรารีอย่างถาวร หากต้องการตั้งค่าชั่วคราว ให้ใช้ตัวแปรสภาพแวดล้อม LD_LIBRARY_PATH บนบรรทัดคำสั่ง หากคุณต้องการเก็บการเปลี่ยนแปลงอย่างถาวร ให้เพิ่มบรรทัดนี้ในไฟล์การกำหนดค่าเริ่มต้นเชลล์ /etc/profile (ทั่วโลก) หรือ ~/.profile (เฉพาะผู้ใช้)
export LD_LIBRARY_PATH=/path/to/library/file
การจัดการไลบรารีที่ใช้ร่วมกันใน Linux
ตอนนี้เรามาดูวิธีจัดการกับไลบรารีที่แชร์กัน หากต้องการรับรายการการพึ่งพาไลบรารีที่ใช้ร่วมกันทั้งหมดสำหรับไฟล์ไบนารี คุณสามารถใช้ ยูทิลิตี ldd ผลลัพธ์ของ ldd อยู่ในรูปแบบ:
library name => filename (some hexadecimal value)
OR
filename (some hexadecimal value) #this is shown when library name can’t be read
คำสั่งนี้แสดงการพึ่งพาไลบรารีที่แบ่งใช้ทั้งหมดสำหรับคำสั่ง ls
ldd /usr/bin/ls
OR
ldd /bin/ls
ผลลัพธ์ตัวอย่าง
linux-vdso.so.1 => (0x00007ffebf9c2000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x0000003b71e00000)
librt.so.1 => /lib64/librt.so.1 (0x0000003b71600000)
libcap.so.2 => /lib64/libcap.so.2 (0x0000003b76a00000)
libacl.so.1 => /lib64/libacl.so.1 (0x0000003b75e00000)
libc.so.6 => /lib64/libc.so.6 (0x0000003b70600000)
libdl.so.2 => /lib64/libdl.so.2 (0x0000003b70a00000)
/lib64/ld-linux-x86-64.so.2 (0x0000561abfc09000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003b70e00000)
libattr.so.1 => /lib64/libattr.so.1 (0x0000003b75600000)
เนื่องจากไลบรารีแบบแบ่งใช้สามารถมีอยู่ในไดเร็กทอรีต่างๆ มากมาย การค้นหาไดเร็กทอรีเหล่านี้ทั้งหมดเมื่อเปิดโปรแกรมอาจไม่มีประสิทธิภาพมากนัก ซึ่งเป็นหนึ่งในข้อเสียที่เป็นไปได้ของไดนามิกไลบรารี ดังนั้นจึงมีการใช้กลไกการแคช ซึ่งดำเนินการโดยโปรแกรม ldconfig
ตามค่าเริ่มต้น ldconfig อ่านเนื้อหาของ /etc/ld.so.conf สร้างลิงก์สัญลักษณ์ที่เหมาะสมในไดเร็กทอรีลิงก์แบบไดนามิก จากนั้นจึงเขียนแคชไปที่ /etc/ld.so.cache ซึ่งจะทำให้โปรแกรมอื่นนำไปใช้ได้อย่างง่ายดาย
สิ่งนี้สำคัญมากโดยเฉพาะอย่างยิ่งเมื่อคุณเพิ่งติดตั้งไลบรารีที่แบ่งใช้ใหม่หรือสร้างขึ้นเอง หรือสร้างไดเร็กทอรีไลบรารีใหม่ คุณต้องเรียกใช้คำสั่ง ldconfig เพื่อให้การเปลี่ยนแปลงมีผล
ldconfig
OR
ldconfig -v #shows files and directories it works with
หลังจากสร้างไลบรารีที่ใช้ร่วมกันแล้ว คุณจะต้องติดตั้งไลบรารีดังกล่าว คุณสามารถย้ายไปยังไดเรกทอรีมาตรฐานใดก็ได้ที่กล่าวถึงข้างต้น และเรียกใช้คำสั่ง ldconfig
หรือเรียกใช้คำสั่งต่อไปนี้เพื่อสร้างลิงก์สัญลักษณ์จาก soname ไปยังชื่อไฟล์:
ldconfig -n /path/to/your/shared/libraries
หากต้องการเริ่มต้นสร้างไลบรารีของคุณเอง โปรดดูคู่มือนี้จาก The Linux Documentation Project (TLDP)
นั่นคือทั้งหมดที่สำหรับตอนนี้! ในบทความนี้ เราได้ให้ข้อมูลเบื้องต้นเกี่ยวกับไลบรารีและอธิบายไลบรารีแบบแบ่งใช้ ตลอดจนวิธีจัดการไลบรารีเหล่านั้นใน Linux หากคุณมีข้อสงสัยหรือแนวคิดเพิ่มเติมที่จะแบ่งปัน โปรดใช้แบบฟอร์มความคิดเห็นด้านล่าง