เชลล์ดำเนินการโปรแกรมอย่างไร


11

หากฉันรวบรวมโปรแกรมโดยใช้ gcc และลองเรียกใช้งานจาก bash shell อะไรคือลำดับขั้นตอนที่แน่นอนตามด้วย bash เพื่อเรียกใช้งานมัน

ฉันรู้fork(), execve(), loader, dynamic linker(และสิ่งอื่น ๆ ) มีส่วนร่วม แต่คนที่สามารถให้ลำดับขั้นตอนอย่างและบางส่วนอ้างอิงการอ่านที่เหมาะสม?

แก้ไข:

จากคำตอบดูเหมือนว่าคำถามอาจบ่งบอกถึงความเป็นไปได้มากมาย ฉันต้องการแคบลงเป็นกรณีง่ายๆ:

(test.c เพียงพิมพ์ Hello world)

$ gcc test.c -o test
$ ./test

สิ่งที่จะเป็นขั้นตอนในกรณีข้างต้น ( ./test) โดยเฉพาะที่เกี่ยวข้องกับโปรแกรมเริ่มต้นทุบตีในกระบวนการเด็กบางอย่างที่ทำโหลดเชื่อมโยง ฯลฯ ?


4
ฉันขอเชิญคุณอ่านlwn.net/Articles/630727
cuonglm

3
ทำไมไม่ลอง `strace bash -c 'test'?
Sergiy Kolodyazhnyy

2
ดูเหมือนว่าตำราระบบปฏิบัติการที่ดีจะเป็นแหล่งข้อมูลที่ดีสำหรับ OP การพยายามที่จะเรียนรู้ว่าระบบปฏิบัติการทำงานอย่างไรโดยการถามคำถามแบบนี้ไม่น่าจะเป็นกระบวนการที่มีประสิทธิผล
Barmar

มันจะมีประโยชน์ในการดูตัวอย่างของเชลล์: brennan.io/2015/01/16/write-a-shell-in-c
jinawee

คำตอบ:


5

ลำดับที่แน่นอนอาจแตกต่างกันเนื่องจากอาจมีนามแฝงของเชลล์หรือฟังก์ชั่นที่ได้รับการขยาย / ตีความก่อนที่โปรแกรมจริงจะถูกดำเนินการและจากนั้นความแตกต่างสำหรับชื่อไฟล์ที่ผ่านการรับรอง ( /usr/libexec/foo) กับบางสิ่งที่จะค้นหาผ่านไดเรกทอรีทั้งหมด ของPATHตัวแปรสภาพแวดล้อม (เพียงfoo) นอกจากนี้ยังมีรายละเอียดการดำเนินการที่อาจจะยุ่งเรื่องเช่นfoo | bar | zotต้องทำงานมากขึ้นสำหรับเปลือก (จำนวนบางfork(2), dup(2)และแน่นอนpipe(2)ท่ามกลางสายระบบอื่น ๆ ) ในขณะที่สิ่งที่ต้องการexec fooคือการทำงานมากน้อยเป็นเปลือกเพียงแทนที่ตัวเองด้วย โปรแกรมใหม่ (เช่นมันไม่ได้fork) ที่สำคัญก็คือกลุ่มกระบวนการ (โดยเฉพาะกลุ่มกระบวนการเบื้องหน้าซึ่ง PID ทั้งหมดที่กินSIGINTเมื่อมีคนเริ่ม mashing ในCtrl+ C, เซสชันและไม่ว่างานจะถูกเรียกใช้ในพื้นหลัง, monitored ( foo &) หรือพื้นหลัง, ละเว้น ( foo & disown) รายละเอียดการเปลี่ยนเส้นทาง I / O จะเปลี่ยนสิ่งต่าง ๆ เช่นถ้าอินพุตมาตรฐานถูกปิดโดยเชลล์ ( foo <&-) หรือว่าไฟล์ถูกเปิดเป็น stdin ( foo < blah)

straceหรือคล้ายกันจะให้ข้อมูลเกี่ยวกับการเรียกระบบเฉพาะที่ทำตามกระบวนการนี้และควรมี man page สำหรับแต่ละการเรียกเหล่านั้น การอ่านระดับระบบที่เหมาะสมจะเป็นจำนวนบทใด ๆ จาก "การเขียนโปรแกรมขั้นสูงในสภาพแวดล้อม UNIX" ของสตีเวนส์ในขณะที่หนังสือเชลล์ (เช่น "จาก Bash ถึง Z Shell") จะครอบคลุมรายละเอียดเพิ่มเติมของเชลล์


ฉันแก้ไขคำถามให้แคบลงเป็นกรณีที่ง่าย
Jake

1

สมมติว่าเชลล์ตัวอย่างตำราเรียน (สำหรับรหัสความคมชัด) ที่กำลังทำงานอยู่ (เพื่อให้ลิงเกอร์แบบไดนามิกเสร็จสิ้น) คำสั่งที่คุณพูดถึงจะต้องใช้เชลล์เพื่อทำการเรียกใช้ระบบต่อไปนี้:

  • อ่าน: รับคำสั่งถัดไปในกรณีนี้ gcc
  • ทางแยก: จำเป็นต้องใช้สองกระบวนการเราถือว่าผู้ปกครองมี pid 500 และลูกเพื่อเป็นตัวอย่าง
  • ผู้ปกครองจะเรียกรอ (501) ในขณะที่เด็กจะเรียก exec ณ จุดนี้เชลล์ไม่ทำงานบน pid 501 อีกต่อไป gcc ทำการเรียกใช้ระบบจำนวนมากรวมถึงอย่างน้อยเปิดปิดอ่านอ่านเขียน chmod ส้อม fork ผู้บริหารรอและออก
  • เมื่อการเรียก gcc จบลงการรอจะส่งคืนการเขียนจะถูกเรียกเพื่อแสดงพรอมต์และกระบวนการจะทำซ้ำ

คำสั่งที่ซับซ้อนมากขึ้นของหลักสูตรเพิ่มความซับซ้อนมากขึ้นในลำดับขั้นพื้นฐานนี้ ตัวอย่างที่ง่ายกว่าของภาวะแทรกซ้อนพื้นฐานคือการเปลี่ยนเส้นทาง io พื้นฐานที่มีการแทรกลำดับเปิดปิดและดูซ้ำระหว่าง fork และกระบวนการ exec และพื้นหลังที่การรอคอยถูกข้ามไป


เพิ่มเติมเล็กน้อย: คำถามถามเกี่ยวกับการโหลดและการเชื่อมโยงแบบไดนามิก โค้ดทั้งหมดที่ลิงก์แบบสแตติกเช่นถูกรวมไว้ในไฟล์โปรแกรมนั้นทำโดยเคอร์เนลก่อนที่โปรแกรมจะเริ่มต้น ไลบรารีที่โหลดแบบไดนามิกเช่นไฟล์ที่แยกต่างหากได้รับการจัดการโดยตัวโปรแกรมเองก่อนที่จะเริ่ม main () รหัสนี้จะถูกเพิ่มโดย gcc โดยอัตโนมัติ
เฮมเมอร์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.