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 **)evalbltinevalevalcmdecho
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คำสั่ง