เหตุใดจึงls
ต้องมีกระบวนการแยกต่างหากสำหรับการดำเนินการ ฉันรู้ว่าสาเหตุที่คำสั่งเช่นcd
ไม่สามารถดำเนินการได้โดยกลไกการฟอร์กกิ้ง แต่มีอันตรายใด ๆ หากls
ถูกสั่งการโดยไม่ฟอร์กกิ้ง?
เหตุใดจึงls
ต้องมีกระบวนการแยกต่างหากสำหรับการดำเนินการ ฉันรู้ว่าสาเหตุที่คำสั่งเช่นcd
ไม่สามารถดำเนินการได้โดยกลไกการฟอร์กกิ้ง แต่มีอันตรายใด ๆ หากls
ถูกสั่งการโดยไม่ฟอร์กกิ้ง?
คำตอบ:
คำตอบนั้นมากขึ้นหรือน้อยลงที่ls
สามารถเรียกใช้งานได้จากภายนอก type -p ls
คุณสามารถดูสถานที่ของตนโดยการเรียกใช้
ทำไมไม่ls
สร้างไว้ในเชลล์ล่ะ? ทำไมมันถึงเป็นอย่างนั้น? งานของเชลล์ไม่ได้รวมทุกคำสั่งที่มีอยู่ แต่เพื่อจัดเตรียมสภาพแวดล้อมที่สามารถเรียกใช้งานได้ กระสุนสมัยใหม่บางรุ่นมีecho
, printf
และ, ตระกูลของพวกเขาเป็น builtins, ซึ่งโดยทางเทคนิคไม่จำเป็นต้องเป็น buildins, แต่ถูกสร้างขึ้นมาเพื่อเหตุผลด้านประสิทธิภาพเมื่อพวกมันถูกเรียกใช้ซ้ำ ๆ เชลล์จะต้องแยกและดำเนินกระบวนการใหม่สำหรับการเรียกแต่ละครั้งซึ่งอาจช้ามาก
อย่างน้อยที่สุดการรันไฟล์เรียกทำงานls
ภายนอกต้องรันหนึ่งในตระกูล exec ของการเรียกระบบ คุณสามารถทำได้โดยไม่ต้องฟอร์ก แต่จะแทนที่เชลล์หลักที่คุณใช้อยู่ คุณสามารถดูว่าเกิดอะไรขึ้นในอินสแตนซ์นั้นโดยทำสิ่งต่อไปนี้:
exec ls; echo "this never gets printed"
เนื่องจากอิมเมจกระบวนการเชลล์ของคุณถูกแทนที่เชลล์ปัจจุบันจะไม่สามารถเข้าถึงได้หลังจากทำสิ่งนี้แล้ว เพื่อให้เชลล์สามารถรันต่อไปหลังจากรัน ls คำสั่งจะต้องสร้างขึ้นในเชลล์
Forking อนุญาตให้เปลี่ยนกระบวนการที่ไม่ใช่เชลล์หลักของคุณซึ่งหมายความว่าคุณสามารถรันเชลล์ต่อได้ในภายหลัง
echo
, printf
ฯลฯ
cd
ไม่สามารถเรียกใช้งานภายนอกได้
cd
ที่ปฏิบัติการในระบบปฏิบัติการที่สอดคล้องกับ POSIX ( ดูที่นี่ ) หากคุณต้องการ chdir () จริง ๆ ในกระบวนการปัจจุบันคุณต้องสร้างมันไว้ในเชลล์
คำสั่งในตัวมีความจำเป็นต่อการใช้งานฟังก์ชั่นที่เป็นไปไม่ได้หรือไม่สะดวกในการขอรับด้วยยูทิลิตี้แยก
นั่นคือเปลือกหอยถูกออกแบบมาเพื่อเท่านั้นรวมคำสั่งในตัวเท่านั้นหาก:
ls
คำสั่งไม่เหมาะสมใด ๆ ของข้อกำหนดดังกล่าวข้างต้น
อย่างไรก็ตามนี่คือข้อ จำกัด การเขียนโปรแกรมที่จะป้องกันไม่ให้ ls
ถูกฝังอยู่ในตัวที่กำลังดำเนินการในกระบวนการเดียวกับล่ามทุบตี เหตุผลการออกแบบสำหรับคำสั่งที่ไม่ได้รับการฝังอยู่ในตัวเชลล์คือ:
เกี่ยวกับเหตุผลแรก - คุณต้องการให้เชลล์มีความเป็นอิสระและมีความยืดหยุ่นมากที่สุด คุณไม่ต้องการให้เชลล์ติดกับls
NFS mount นั่นคือ "ไม่ตอบสนองยังคงพยายาม"
เกี่ยวกับเหตุผลข้อที่สอง - ในหลาย ๆ กรณีคุณอาจต้องการใช้เชลล์สำหรับระบบที่ใช้ Busybox หรือระบบไฟล์อื่น ๆ ที่มีการls
ใช้งานที่แตกต่างกัน หรือแม้แต่ใช้เชลล์ซอร์สเดียวกันใน OS ของที่มีความแตกต่างกันls
การใช้งานที่
เกี่ยวกับเหตุผลที่สาม - สำหรับการแสดงออกเช่นfind . -type d | xargs ls -lad
มันจะเป็นเรื่องยากหรือเป็นไปไม่ได้ที่จะใช้ls
ในกระบวนการเดียวกับล่ามเปลือก
เกี่ยวกับเหตุผลข้อที่สี่ - ls
คำสั่งบางคำสั่งอาจใช้เวลานานกว่าจะสำเร็จ คุณอาจต้องการให้เชลล์ดำเนินการอย่างอื่นต่อไปในระหว่างนี้
หมายเหตุ: ดูโพสต์ที่เป็นประโยชน์นี้โดยWarren Youngเพื่อตอบคำถามที่คล้ายกัน
ls
ลงในกระบวนการภายนอก มันสามารถทำได้ แต่มันจะซับซ้อน
bash
alias | grep ls
อินพุตcat /etc/passwd | while read a; do echo "$a"; done
ls
ไม่ต้องใช้กระบวนการแยกต่างหาก จริง ๆ แล้วคำสั่งน้อยมากต้องการกระบวนการแยกต่างหาก: เฉพาะคำสั่งที่ต้องการเปลี่ยนสิทธิ์
ตามกฎแล้วเชลล์ใช้คำสั่งเป็นบิลด์เมื่อจำเป็นต้องใช้คำสั่งเหล่านั้นเป็นบิลด์ คำสั่งเช่นalias
, cd
, exit
, export
, jobs
, ... ต้องอ่านหรือแก้ไขบางรัฐภายในของเปลือกและดังนั้นจึงไม่สามารถเป็นโปรแกรมแยก คำสั่งที่ไม่มีข้อกำหนดดังกล่าวสามารถแยกคำสั่งได้ ด้วยวิธีนี้พวกเขาสามารถเรียกจากเปลือกหรือโปรแกรมอื่น ๆ
การดูรายการบิวด์อินใน bash เฉพาะบิวด์อินต่อไปนี้เท่านั้นที่สามารถใช้เป็นคำสั่งแยก สำหรับบางคนอาจมีการสูญเสียฟังก์ชันการทำงานเล็กน้อย
command
- แต่มันจะเสียประโยชน์ในสถานการณ์ที่PATH
อาจไม่สามารถตั้งค่าได้อย่างถูกต้องและสคริปต์ใช้command
เป็นส่วนหนึ่งของการตั้งค่าecho
- มันเป็น builtin สำหรับประสิทธิภาพhelp
- มันสามารถใช้ฐานข้อมูลแยกจากกันได้ แต่การฝังข้อความช่วยเหลือลงในเชลล์ที่สามารถเรียกใช้งานได้นั้นมีข้อดีของการทำให้เชลล์สามารถเรียกทำงานได้ในตัวkill
- มีข้อดีสองประการในการมี builtin: มันสามารถรับรู้ตำแหน่งงานนอกเหนือจาก ID กระบวนการและสามารถใช้งานได้แม้ว่าจะมีทรัพยากรไม่เพียงพอที่จะเริ่มกระบวนการแยกต่างหากprintf
- ด้วยเหตุผลเดียวกันกับecho
และเพื่อสนับสนุน-v
ตัวเลือกในการใส่ผลลัพธ์ในตัวแปรpwd
- builtin มีความสามารถเพิ่มเติมของการติดตามไดเรกทอรีโลจิคัลปัจจุบัน (ปล่อยให้ลิงก์สัญลักษณ์ไม่เสียหายแทนที่จะขยายออก)test
- มันมีประสิทธิภาพในตัว (และทุบตีด้วยเวทมนตร์ด้วยไฟล์ที่เรียกว่า/dev/fd/…
ระบบปฏิบัติการบางระบบ)กระสุนจำนวนหนึ่งมีจำนวนบิวด์อินเพิ่มขึ้นจำนวนมาก มีสายสะพายซึ่งเป็นเชลล์ที่ออกแบบมาให้เป็นไบนารีแบบสแตนด์อโลนสำหรับการซ่อมแซมฉุกเฉิน (เมื่อคำสั่งภายนอกบางอย่างอาจไม่สามารถใช้งานได้) แต่ก็มีในตัวls
เรียกว่า-ls
เช่นเดียวกับเครื่องมืออื่น ๆ เช่นและ-grep
-tar
บิวด์อินของ Sash มีความสามารถน้อยกว่าคำสั่งแบบเต็ม ข้อเสนอ zsh builtins ที่คล้ายกันบางอย่างในของzsh โมดูล มันไม่ได้มีls
แต่การขยายตัวสัญลักษณ์ ( echo *
) และzstat
สามารถให้บริการฟังก์ชั่นที่คล้ายกัน
ฉันคิดว่าสิ่งที่คนขาดหายไปในที่นี้คือความซับซ้อนของการเฉือนของls
โปรแกรมGNU บน Linux เมื่อเปรียบเทียบขนาดที่สามารถใช้งานได้ของls
ไปยังbash
และdash
เชลล์บนระบบ Debian ของเราเราเห็นว่ามันมีขนาดค่อนข้างใหญ่:
graeme@graeme:~$ ls -lh /bin/{ls,bash,dash}
-rwxr-xr-x 1 root root 953K Mar 30 2013 /bin/bash
-rwxr-xr-x 1 root root 115K Dec 25 20:25 /bin/dash
-rwxr-xr-x 1 root root 108K Jul 20 22:52 /bin/ls
การรวมฟีเจอร์ls
เต็มรูปแบบเช่นเดียวกับ GNU เวอร์ชั่นbash
จะเพิ่มขนาดไฟล์เรียกทำงานได้ 10% มันเกือบจะเป็นขนาดเดียวกับdash
กระสุนเต็ม!
บิวด์เชลล์ส่วนใหญ่จะถูกเลือกเพราะมันรวมเข้ากับเชลล์ในวิธีที่เอ็กซีคิวต์ภายนอกไม่สามารถทำได้ (คำถามชี้ให้เห็นcd
แต่อีกตัวอย่างหนึ่งคือเวอร์ชันทุบตีของkill
การรวมเข้ากับการควบคุมงานทุบตี) หรือเพราะเป็นคำสั่งที่ง่ายมาก ให้ความเร็วที่มากเทียบกับขนาดผลตอบแทน ( true
และfalse
เป็นเรื่องง่ายเท่าที่จะได้รับ)
GNU ls
มีวัฏจักรการพัฒนาที่ยาวนานและอาจมีตัวเลือกในการปรับแต่งผลลัพธ์ที่แสดง การใช้ builtin ls เป็นค่าเริ่มต้นอาจสูญเสียฟังก์ชันการทำงานนี้หรือเพิ่มความซับซ้อนและขนาดของเชลล์
cd
ถูกสร้างขึ้นในเปลือกเป็นโปรแกรมแยกต่างหากที่คุณจะเห็นที่ls
/bin/ls
ทำสิ่งที่คุณกำลังมองหา:
printf "%s\n" *
นอกจากนี้คุณสามารถจัดเก็บชื่อไฟล์ในอาร์เรย์:
files=(`printf "%s\n" *`) #items are separated by whitespace
echo ${#files[*]} files
for index in ${!a[*]}
do printf "%d: %s\n" $index ${a[$index]};
done
แต่มันไม่สนใจช่องว่างในชื่อ
สิ่งนี้ส่งผ่านไปยังตัวแปรและไม่สนใจช่องว่าง:
printf "%s\n" * | while read a; do echo $a; done
ls
จะเป็นโปรแกรมภายนอกecho *
หรือecho * .*
(ขึ้นอยู่กับตัวเลือกของเชลล์) ทำงานได้ค่อนข้างดีในการแสดงรายการไฟล์โดยไม่ต้องฟอร์ก