cd
เป็นเชลล์ในตัวของPOSIX :
หากคำสั่งอย่างง่ายส่งผลให้ชื่อคำสั่งและรายการอาร์กิวเมนต์ที่เลือกระบุได้จะต้องดำเนินการดังต่อไปนี้:
- หากชื่อคำสั่งไม่มีเครื่องหมายทับใด ๆ ขั้นตอนแรกที่สำเร็จในลำดับต่อไปนี้จะเกิดขึ้น:
...
- หากชื่อคำสั่งตรงกับชื่อของยูทิลิตี้ที่แสดงในตารางต่อไปนี้ยูทิลิตีนั้นจะถูกเรียกใช้
...
cd
...
- มิฉะนั้นคำสั่งจะถูกค้นหาเพื่อใช้เส้นทาง ...
ในขณะที่สิ่งนี้ไม่ได้บอกอย่างชัดเจนว่ามันจะต้องมีมาพร้อมกับตัวเครื่อง แต่ในรายละเอียดของcd
:
เนื่องจาก cd ส่งผลกระทบต่อสภาพแวดล้อมการประมวลผลเชลล์ในปัจจุบันจึงมีการจัดให้เป็นเชลล์ในตัวปกติเสมอ
จากbash
คู่มือ :
คำสั่ง buildin ของเชลล์ต่อไปนี้สืบทอดมาจาก Bourne Shell คำสั่งเหล่านี้ถูกนำไปใช้ตามที่ระบุโดยมาตรฐาน POSIX
...
cd
cd [-L|[-P [-e]]] [directory]
ฉันคิดว่าคุณคงนึกถึงสถาปัตยกรรมที่cd
ไม่จำเป็นต้องเป็นแบบบิลท์อิน อย่างไรก็ตามคุณต้องดูว่ามีอะไรในตัว หากคุณเขียนโค้ดพิเศษลงในเชลล์เพื่อทำบางสิ่งบางอย่างสำหรับคำสั่งบางอย่างคุณจะเข้าใกล้การมีบิวด์อิน ยิ่งคุณทำมากเท่าไหร่ก็จะยิ่งมีตัวบิวด์อินเท่านั้น
ตัวอย่างเช่นคุณอาจมีเชลล์ที่มี IPC เพื่อสื่อสารกับกระบวนการย่อยและจะมีcd
โปรแกรมที่จะตรวจสอบว่ามีไดเรกทอรีอยู่หรือไม่และคุณมีสิทธิ์ในการเข้าถึงหรือไม่จากนั้นสื่อสารกับเชลล์เพื่อบอกให้เปลี่ยน ไดเรกทอรี อย่างไรก็ตามคุณจะต้องตรวจสอบว่ากระบวนการสื่อสารกับคุณเป็นเด็กหรือไม่ (หรือใช้วิธีการสื่อสารพิเศษกับเด็ก ๆ เท่านั้นเช่นตัวอธิบายไฟล์พิเศษหน่วยความจำที่แชร์ ฯลฯ ) และหากเป็นกระบวนการจริง เรียกใช้cd
โปรแกรมที่เชื่อถือได้หรืออย่างอื่น นั่นคือความสามารถทั้งหมดของเวิร์ม
หรือคุณอาจมีcd
โปรแกรมที่ทำให้การchdir
เรียกของระบบและเริ่มเชลล์ใหม่ด้วยตัวแปรสภาพแวดล้อมปัจจุบันทั้งหมดที่ใช้กับเชลล์ใหม่แล้วฆ่า parent parent (อย่างใด) เมื่อเสร็จแล้ว 1
ที่แย่กว่านั้นคือคุณอาจมีระบบที่กระบวนการสามารถเปลี่ยนแปลงสภาพแวดล้อมของกระบวนการอื่น ๆ (ฉันคิดว่าในทางเทคนิคคุณสามารถทำสิ่งนี้กับ debuggers) อย่างไรก็ตามระบบดังกล่าวจะมีความเสี่ยงมาก
คุณจะพบว่าตัวเองเพิ่มรหัสมากขึ้นเพื่อความปลอดภัยของวิธีการดังกล่าวและมันก็ง่ายกว่ามากที่จะทำให้มันเป็นแบบบิวด์อิน
สิ่งที่เป็นไฟล์ปฏิบัติการไม่ได้ป้องกันไม่ให้มันเป็นบิวอิน กรณีในจุด:
echo
และ test
echo
และtest
เป็นโปรแกรมอรรถประโยชน์ที่ได้รับคำสั่ง POSIX ( /bin/echo
และ/bin/test
) แต่เชลล์ยอดนิยมเกือบทุกตัวมีตัวต่อecho
และtest
ภายใน ในทำนองเดียวกันkill
ก็สร้างขึ้นในที่มีอยู่ในโปรแกรม อื่น ๆ ได้แก่ :
sleep
(ไม่เหมือนกัน)
time
false
true
printf
อย่างไรก็ตามมีบางกรณีที่คำสั่งไม่สามารถเป็นอะไรได้นอกจากบิลด์อิน cd
หนึ่งในนั้นคือ โดยทั่วไปหากไม่ระบุพา ธ เต็มและชื่อคำสั่งตรงกับของบิวด์อินฟังก์ชันที่เหมาะสมกับคำสั่งนั้นจะถูกเรียกใช้ ขึ้นอยู่กับเชลล์พฤติกรรมของ builtin และของ executable อาจแตกต่างกัน (นี่เป็นปัญหาecho
โดยเฉพาะอย่างยิ่งซึ่งมีพฤติกรรมที่แตกต่างกันอย่างดุเดือดหากคุณต้องการให้แน่ใจถึงพฤติกรรมบางอย่าง เส้นทางแบบเต็มและตั้งค่าตัวแปรเช่นPOSIXLY_CORRECT
(แม้ว่าจะไม่มีการรับประกันจริง)
ในทางเทคนิคไม่มีอะไรที่ขัดขวางไม่ให้คุณจัดหาระบบปฏิบัติการที่เป็นเชลล์และมีทุกคำสั่งในตัว ใกล้ถึงจุดสิ้นสุดที่รุนแรงนี้เป็นเสาหินBusyBox BusyBox เป็นไบนารีเดียวที่ (ขึ้นอยู่กับชื่อที่ใช้เรียก) สามารถทำงานได้เหมือนโปรแกรมใด ๆมากกว่า 240 โปรแกรมรวมถึง Almquist Shell ( ash
) หากคุณล้างค่าPATH
ในขณะที่การทำงานของ BusyBox ash
โปรแกรมที่มีอยู่ใน BusyBox PATH
ยังสามารถเข้าถึงได้ให้กับคุณโดยไม่ได้ระบุ พวกเขาเข้ามาใกล้กับเชลล์บิวด์อินยกเว้นว่าเชลล์นั้นเป็นบิวด์บิวด์ใน BusyBox
หากคุณดูที่dash
แหล่งข้อมูลเธรดการเรียกใช้งานจะมีลักษณะดังนี้ (แน่นอนพร้อมฟังก์ชันเพิ่มเติมที่เกี่ยวข้องเมื่อใช้ไพพ์และสิ่งอื่น ๆ ):
main
→การcmdloop
→การevaltree
→การevalcommand
evalcommand
จากนั้นใช้findcommand
เพื่อกำหนดว่าคำสั่งคืออะไร ถ้ามันเป็น builtin แล้ว :
case CMDBUILTIN:
if (spclbltin > 0 || argc == 0) {
poplocalvars(1);
if (execcmd && argc > 1)
listsetvar(varlist.list, VEXPORT);
}
if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
if (exception == EXERROR && spclbltin <= 0) {
FORCEINTON;
break;
cmdentry.u.cmd
เป็นstruct
( struct builtincmd
) หนึ่งซึ่งมีสมาชิกเป็นตัวชี้ทำงานด้วยลายเซ็นตามแบบฉบับของ:main
เรียกฟังก์ชัน (ขึ้นอยู่กับว่า builtin เป็นคำสั่งหรือไม่) อย่างใดอย่างหนึ่งหรือตัวชี้ฟังก์ชั่นนี้ ฟังก์ชั่นที่แท้จริงถูกกำหนดไว้ในไฟล์ต้นฉบับต่างๆ ตัวอย่างเช่นคือ :(int, char **)
evalbltin
eval
evalcmd
echo
int
echocmd(int argc, char **argv)
{
int nonl;
nonl = *++argv ? equal(*argv, "-n") : 0;
argv += nonl;
do {
int c;
if (likely(*argv))
nonl += print_escape_str("%s", NULL, NULL, *argv++);
if (nonl > 0)
break;
c = *argv ? ' ' : '\n';
out1c(c);
} while (*argv);
return 0;
}
ลิงก์ไปยังซอร์สโค้ดทั้งหมดในส่วนนี้ขึ้นอยู่กับจำนวนบรรทัดดังนั้นจึงอาจมีการเปลี่ยนแปลงโดยไม่ต้องแจ้งให้ทราบล่วงหน้า
1ระบบ POSIX มีcd
ไฟล์เรียกทำงานได้
หมายเหตุด้านข้าง:
มีโพสต์ที่ยอดเยี่ยมมากมายบน Unix & Linux ที่จัดการกับพฤติกรรมของเชลล์ โดยเฉพาะอย่างยิ่ง:
หากคุณไม่ได้สังเกตเห็นรูปแบบในคำถามที่ระบุไว้เพื่อให้ห่างไกลเกือบทั้งหมดของพวกเขาเกี่ยวข้องกับStéphane Chazelas
type
คำสั่ง