init ทำอะไรได้บ้าง?


43

ฉันกำลังสร้างลินุกซ์ distro และตอนนี้ฉันต้องการโปรแกรมเริ่มต้น ฉันสามารถเขียนโค้ดใน c ได้ดีมากและฉันรู้ค่อนข้างน้อยเกี่ยวกับ linux (ไม่มาก แต่ฉันใช้ arch linux สำหรับการพัฒนาเป็นเวลา 4 ปี) ดังนั้นฉันคิดว่าฉันควรลองเขียนสคริปต์ init พื้นฐานของฉันเองใน C ฉัน แค่สงสัยว่างานเริ่มต้นทำอะไรเพื่อตั้งค่าระบบสำหรับเชลล์แบบง่าย? (เมื่อฉันถามว่า "init ทำอะไรได้บ้าง" ฉันรู้ว่า init คืออะไรและใช้ทำอะไรฉันไม่ทราบว่าจะทำงานอะไร)

ฉันไม่จำเป็นต้องรหัสและฉันอาจไม่จำเป็นต้องมีแม้แต่คำสั่งพื้นฐาน แต่ฉันไม่ต้องการเพื่อที่พวกเขาจะทำงานใน


1
คุณสามารถใช้ล่ามอะไรก็ได้ที่คุณต้องการสำหรับสคริปต์เริ่มต้นของ SysV ซึ่งรวมถึง Perl, awk, bash, (t) csh, ไบนารีเนทีฟ, ... Bash ถูกใช้งานตามปกติ ปรับใช้ที่จุดที่เกี่ยวข้องในกระบวนการบูตไม่ใช่เพราะมีการเชื่อมต่อระหว่าง SysVinit และ bash SysVinit กำหนดสัญญาและแต่ละสคริปต์มีอิสระที่จะใช้สัญญานั้นไม่ว่าในทางใดก็ตามที่ผู้พัฒนาเห็นว่าเหมาะสม
CVn

คำตอบ:


53

ระบบ 5 initจะบอกคุณเพียงส่วนเล็ก ๆ ของเรื่องราว

สายตาสั้นนั้นมีผลกระทบต่อโลกลีนุกซ์ ผู้คนคิดว่าพวกเขาใช้สิ่งที่เรียกว่า "ระบบ 5 init" และนั่นคือสิ่งที่เป็นแบบดั้งเดิมและเป็นจุดเริ่มต้นที่ดีที่สุด ในความเป็นจริงทั้งสองกรณี

ประเพณีไม่ได้อยู่ในความเป็นจริงสิ่งที่คนเช่นนี้บอกว่ามันจะเป็นสำหรับการเริ่ม ระบบ 5 initและrcวันที่5 ของระบบสำหรับ AT&T UNIX System 5 ซึ่งเกือบจะเป็นหลัง UNIX แรกเท่าที่เราเป็นตอนนี้หลังจากพูดคุยกับ Linux-Mandrake รุ่นแรก

ฉบับที่ 1 UNIX initมีเพียง rcมันไม่ได้มี ภาษาแอสเซมบลีรุ่นที่ 1 init( ซึ่งโค้ดได้รับการกู้คืนและทำให้พร้อมใช้งานโดย Warren Toomey และคณะ ) วางกระบวนการโดยตรงและเกิดใหม่ 12 gettyกระบวนการติดตั้งระบบไฟล์เดินสาย 3 ชุดจากตารางในตัวและเรียกใช้โปรแกรมโดยตรงจากโฮมไดเรกทอรีของ melชื่อผู้ใช้ gettyตารางก็ยังโดยตรงในภาพโปรแกรม

อีกสิบปีถัดมาหลังจาก UNIX System 5 ระบบลีนุกซ์ Linux ดั้งเดิมที่เรียกว่า ในปี 1992 Miquel van Smoorenburg (อีกครั้ง) เขียน Linux init+ rcและเครื่องมือที่เกี่ยวข้องซึ่งตอนนี้ผู้คนเรียกว่า "ระบบ 5 init" แม้ว่ามันจะไม่ใช่ซอฟต์แวร์จาก UNIX System 5 (และไม่ใช่แค่init)

ระบบ 5 init/ rcไม่ใช่จุดเริ่มต้นที่ดีที่สุดและแม้ว่าจะเพิ่มความรู้เกี่ยวกับ systemd ที่ไม่ครอบคลุมครึ่งหนึ่งของสิ่งที่ควรรู้ มีงานมากมายในการออกแบบระบบเริ่มต้น (สำหรับ Linux และ BSD) ที่เกิดขึ้นในช่วงสองทศวรรษที่ผ่านมาเพียงอย่างเดียว การตัดสินใจทางวิศวกรรมทุกประเภทได้รับการพูดคุยทำออกแบบนำไปปฏิบัติและฝึกฝน Unices เชิงพาณิชย์ก็มีจำนวนมากเช่นกัน

ระบบที่มีอยู่เพื่อศึกษาและเรียนรู้จาก

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

  • finitของ Joachim Nilsson เป็นเส้นทางของการใช้ไฟล์การกำหนดค่าที่มนุษย์อ่านได้มากขึ้น
  • minitของ Felix von Leitner ไปสำหรับระบบการกำหนดค่า filesystem-is-the-database, footprints หน่วยความจำขนาดเล็กและการเริ่ม / หยุดการพึ่งพาระหว่างสิ่งต่าง ๆ ที่initเริ่มขึ้น
  • Runitของ Gerrit Pape ไปสำหรับสิ่งที่ฉันได้อธิบายไว้ก่อนหน้านี้ว่าเป็นวิธีการวางสคริปต์เชลล์สี่ตัว
  • InitNGมีวัตถุประสงค์เพื่อให้มีการขึ้นต่อกันชื่อเป้าหมายไฟล์การกำหนดค่าหลายไฟล์และไวยากรณ์การกำหนดค่าที่ยืดหยุ่นมากขึ้นพร้อมการตั้งค่าโหลดทั้งหมดสำหรับกระบวนการลูก
  • พุ่งพรวดไปสำหรับการออกแบบที่สมบูรณ์การสร้างแบบจำลองระบบไม่ได้เป็นบริการและการพึ่งพาซึ่งกันและกันทั้งหมด แต่เป็นเหตุการณ์และงานทริกเกอร์โดยพวกเขา
  • การออกแบบของnoshรวมถึงการผลักดันการจัดการบริการทั้งหมดออก (รวมถึงการgettyวางไข่และวางไข่ซอมบี้) ในผู้จัดการบริการแยกต่างหากและเพียงแค่จัดการ "API" อุปกรณ์ / symlinks / ไดเรกทอรีและระบบเหตุการณ์
  • sinitคือการเริ่มต้นที่ง่ายมาก มันดำเนิน/bin/rc.initงานซึ่งก็คือการเริ่มโปรแกรมติดตั้งระบบแฟ้ม ฯลฯ สำหรับนี้คุณสามารถใช้สิ่งที่ต้องการminirc

นอกจากนี้ประมาณ 10 ปีที่ผ่านมามีการอภิปรายในหมู่ผู้ใช้ daemontools และอื่น ๆ ของการใช้svscanเป็นกระบวนการที่ 1 ซึ่งนำไปสู่โครงการเช่นพอล Jarc ของ svscan เป็นกระบวนการที่ 1 การศึกษา , ความคิด Gerrit Pape ของและLaurent Bercot ของ svscan เป็นกระบวนการ 1

ซึ่งนำเราไปสู่สิ่งที่โปรแกรม # 1 ทำ

โปรแกรม # 1 ทำอะไร

แนวคิดของสิ่งที่กระบวนการ # 1 คือ "ควร" ที่จะทำคือโดยอัตนัยของพวกเขา เกณฑ์การออกแบบวัตถุประสงค์ที่มีความหมายคือขั้นตอนที่ 1 อย่างน้อยที่สุดที่ต้องทำ เคอร์เนลมีข้อกำหนดหลายประการ และมีบางสิ่งที่เฉพาะเจาะจงกับระบบปฏิบัติการหลายชนิดที่ต้องทำ เมื่อพูดถึงกระบวนการที่ # 1 ได้ทำขึ้นตามธรรมเนียมแล้วเราก็ไม่ได้เป็นอย่างนั้น

มีหลายสิ่งที่เคอร์เนลระบบปฏิบัติการและโปรแกรมอื่น ๆ ต้องการกระบวนการ # 1 ที่ไม่สามารถหลบหนีได้

ผู้คนจะบอกคุณว่าfork()ไอเอ็นจีสิ่งต่าง ๆ และทำหน้าที่เป็นผู้ปกครองของกระบวนการเด็กกำพร้าเป็นหน้าที่สำคัญของกระบวนการ # 1 แดกดันนี่เป็นเรื่องจริง การจัดการกับกระบวนการกำพร้าคือ (กับลินุกซ์ที่ผ่านมาเมล็ดตามที่อธิบายไว้ในhttps://unix.stackexchange.com/a/177361/5132 ) เป็นส่วนหนึ่งของระบบที่หนึ่งสามารถส่วนใหญ่ปัจจัยที่ออกจากกระบวนการ # 1 ในกระบวนการอื่น ๆ เช่น โดยเฉพาะผู้จัดการบริการ ทั้งหมดนี้คือผู้จัดการฝ่ายบริการซึ่งมีกระบวนการที่ 1:

  • โปรแกรม IBM AIX srcmstr, System Resource Controller
  • Gerrit Pape runsvdirจาก runit
  • Daniel J. Bernstein svscanจาก daemontools, Adam Sampson svscanจากfreedt , Bruce Guenter svscanจาก daemontools-encore และ Laurent Bercot s6-svscanจาก s6
  • เวย์นมาร์แชลล์perpdจาก perp
  • สิ่งอำนวยความสะดวกการจัดการบริการใน Solaris 10
  • service-managerจาก Nosh

ในทำนองเดียวกันตามที่อธิบายไว้ที่https://superuser.com/a/888936/38062/dev/initctlแนวคิดทั้งหมดไม่จำเป็นต้องอยู่ใกล้กับกระบวนการ # 1 แดกดันมันเป็น systemd ที่มีการรวมศูนย์สูงซึ่งแสดงให้เห็นว่ามันสามารถถูกย้ายออกจากกระบวนการ # 1

ตรงกันข้ามสิ่งที่จำเป็นสำหรับinitคนที่มักจะลืมในการออกแบบที่ปิดด้านบนของหัวของพวกเขาเป็นสิ่งเช่นการจัดการSIGINT, SIGPWR, SIGWINCHและอื่น ๆ ส่งมาจากเมล็ดและตัวประกันคำขอเปลี่ยนแปลงสถานะของระบบต่างๆส่ง จากโปรแกรมที่ "รู้" ว่าสัญญาณบางอย่างไปยังกระบวนการ # 1 หมายถึงบางสิ่ง (ตัวอย่างเช่น: ตามที่อธิบายไว้ที่https://unix.stackexchange.com/a/196471/5132ชุดเครื่องมือ BSD "รู้" ที่SIGUSR1มีความหมายเฉพาะ)

นอกจากนี้ยังมีการเตรียมใช้งานครั้งเดียวและการทำขั้นตอนสุดท้ายที่ไม่สามารถหลบหนีได้หรือจะประสบปัญหาอย่างมากจากการไม่ทำเช่นการติดตั้งระบบไฟล์ "API"หรือล้างแคชระบบไฟล์

พื้นฐานของการจัดการกับระบบไฟล์ "API" นั้นแตกต่างกันเล็กน้อยกับการทำงานของinitrom 1st Edition UNIX: หนึ่งมีรายการของข้อมูลที่เดินสายเข้าสู่โปรแกรมและหนึ่งmount()รายการทั้งหมดในรายการ คุณจะพบกลไกนี้ในระบบที่มีความหลากหลายเท่ากับ BSD (sic!) initผ่าน nosh system-managerไปจนถึง systemd

"ตั้งค่าระบบสำหรับเชลล์แบบง่าย ๆ "

ตามที่คุณสังเกตเห็นinit=/bin/shไม่ได้รับการติดตั้งระบบไฟล์ "API" ขัดข้องในลักษณะที่ไม่น่าจับตามองโดยไม่ต้องล้างแคชเมื่อหนึ่งประเภทexit( https://unix.stackexchange.com/a/195978/5132 ) และโดยทั่วไปจะทิ้งไว้ ถึงผู้ใช้ (super) เพื่อดำเนินการด้วยตนเองที่ทำให้ระบบใช้งานได้น้อยที่สุด

เมื่อต้องการดูว่าไม่มีใครเลือกจริง แต่ต้องทำในโปรแกรม # 1 ในกระบวนการและทำให้คุณอยู่ในหลักสูตรที่ดีสำหรับเป้าหมายการออกแบบที่ระบุไว้ตัวเลือกที่ดีที่สุดของคุณคือดูการเหลื่อมซ้อนกันในการทำงานของ runit ของ Gerrit Pape Felix von Minit ของ Leitner และsystem-managerโปรแกรมจากแพคเกจ nosh อดีตสองรายการแสดงสองพยายามที่จะเป็นมินิมัลลิสต์ แต่ก็ยังคงจัดการกับสิ่งที่เป็นไปไม่ได้ที่จะหลีกเลี่ยง

อย่างหลังมีประโยชน์ฉันขอแนะนำสำหรับรายการคู่มืออย่างละเอียดสำหรับsystem-managerโปรแกรมซึ่งรายละเอียดว่าระบบไฟล์ "API" ถูกเมาท์งานเริ่มต้นทำงานอะไรและมีการจัดการสัญญาณอะไรบ้าง ในระบบที่ออกแบบโดยผู้จัดการระบบเพิ่งวางไข่สามสิ่งอื่น ๆ (ผู้จัดการบริการ, คนตัดไม้และโปรแกรมเรียกใช้การเปลี่ยนแปลงสถานะ) และทำสิ่งที่หลีกเลี่ยงไม่ได้ในกระบวนการ # 1 เท่านั้น


3
คำตอบที่ยอดเยี่ยมและให้ข้อมูลมาก แต่ฉันถามตัวเองอยู่ในภาพใหญ่นี้เป็น launchdOSX บางครั้งผู้คนก็ลืมไปอย่างสิ้นเชิงว่า OSX นั้นเป็นสมาชิกของครอบครัว * ที่มีขนาดใหญ่
DavAlPi

4

System V init บน Debian (มีตัวแปรและชุดรูปแบบอื่น ๆ ) ทำสิ่งต่อไปนี้:

  • เมื่อเข้าสู่ runlevel จะเรียกสคริปต์/etc/rcX.d/S*ตามลำดับตัวอักษรและตัวเลขที่Xrunlevel สคริปต์เหล่านี้ควรตั้งค่า runlevel การตั้งค่าทั่วไปเริ่มต้น daemons และดำเนินการตั้งค่าสำหรับระดับการทำงานนั้น นี่เป็นสิ่งที่ทำได้เพียงครั้งเดียวเมื่อเข้าสู่ runlevel
  • ในขณะที่อยู่ในระดับการทำงานก็จะเริ่ม daemons ที่ระบุไว้ใน/etc/inittabตามที่จำเป็นต้องใช้งานในช่วงระดับการทำงานที่ หาก daemons เหล่านั้นหยุดทำงานมันจะรีสตาร์ทมัน ในขณะที่คุณสามารถมีภูตใด ๆ ที่คุณต้องการจัดการโดยinitอย่างน้อยคุณต้องการไม่กี่gettyเพื่อให้คุณสามารถเข้าสู่ระบบ gettyออกเมื่อการเข้าสู่ระบบเสร็จสมบูรณ์แล้วinitรีสตาร์ทมันให้รีสตาร์ทพร้อมให้แจ้งเข้าสู่ระบบสด
    • หาก daemon รีสตาร์ทหลายครั้งเกินไปในเวลาอันสั้นมันจะหยุดพยายามรีสตาร์ทสักครู่
    • เพียงเพราะบางสิ่งเริ่มต้นโดยสคริปต์เขี่ยเมื่อเข้าสู่ระดับการวิ่งไม่ได้initพยายามทำให้มันทำงานโดยอัตโนมัติ /etc/inittabคุณต้องระบุที่แยกต่างหากในส่วน
  • เมื่อออกจาก runlevel จะเรียกสคริปต์/etc/rcX.d/K*ตามลำดับตัวอักษรและตัวเลขที่Xrunlevel วิธีที่จะใช้การปิดระบบหรือรีบูตคือการกำหนด runlevel สำหรับเหตุการณ์เหล่านั้นและทำให้งานสุดท้ายที่ดำเนินการคำสั่งhaltหรือreboot
  • มันจะเรียกไฟล์ที่เรียกทำงานได้เพื่อตอบสนองต่อเหตุการณ์บางอย่างเช่นเหตุการณ์พลังงานหรือ Ctrl-Alt-Del
  • มันฟังบนซ็อกเก็ตหากได้รับข้อความบางอย่างมันจะเปลี่ยน runlevel

ดังนั้นคุณสามารถใช้initเป็นผู้จัดการฝ่ายบริการพื้นฐานหากคุณต้องการ แต่ภารกิจหลักในวันนี้คือการทำให้gettyพร้อมใช้งานเพื่อให้ผู้ใช้สามารถเข้าสู่ระบบและเริ่มต้นการเปลี่ยนระดับ runlevel

ฉันแค่สงสัยว่างานเริ่มต้นทำอะไรเพื่อตั้งค่าระบบสำหรับเชลล์อย่างง่าย?

สิ่งที่คุณต้องการ บน Debian ในแต่ละ/etc/rcX.dไดเรกทอรีจะมีลิงก์ไปยังสคริปต์ใน/etc/init.dและคุณสามารถปรับแต่งหรือลบสคริปต์เหล่านั้นได้อย่างเต็มที่ การสั่งซื้อที่จะจัดตั้งขึ้นโดยก่อนหน้านี้แต่ละสคริปต์ด้วย00, 01ฯลฯ

คุณยังสามารถระบุ-bตัวเลือกให้กับinit(เช่นผ่านบรรทัดคำสั่งเคอร์เนล) หากคุณต้องการinitวางไข่เชลล์ เมื่อคุณออกจากเชลล์initตายและเมื่อinitตายเคอร์เนลจะตื่นตระหนก


2

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


1
ฉันเคยมีระบบรถบั๊กกี้ที่ PID 1 หยุดทำงาน แต่ระบบก็ยังทำงานต่อไป ความล้มเหลวของ PID 1 ที่แย่มากขึ้นอยู่กับรุ่นของเคอร์เนล
Gilles 'หยุดชั่วร้าย'

1

init สามารถทำอะไรก็ได้ที่คุณต้องการ

init คือความสามารถในการเรียกใช้งานโดยพลการของเคอร์เนล Linux ในตอนท้ายของกระบวนการบู๊ต

โดยปกติจะมีการใช้งานเป็นไฟล์ปฏิบัติการของ ELF แต่สามารถเป็นเชลล์สคริปต์ได้ด้วยchmod +x: Init เป็นเชลล์สคริปต์

การใช้งานทั่วไปเช่น sysemd จะอ่านไฟล์การกำหนดค่า, ofen /etc/initrc, จากนั้นแยกกลุ่มของกระบวนการ userland ตามการตั้งค่าเหล่านั้น, เพื่อใช้งานด้านต่าง ๆ ของระบบ

อย่างไรก็ตามนี่เป็นการใช้งานที่เฉพาะเจาะจงอย่างสมบูรณ์ดังนั้นคุณจึงไม่สามารถตอบคำถามของคุณได้หากไม่ได้ระบุการใช้งานเฉพาะ ตัวอย่างเช่นฉันได้เล่นกับinitกระบวนการที่ทำrebootsyscallเพียงเพื่อการศึกษา

เคอร์เนล Linux จะค้นหาไฟล์เรียกทำงานที่พา ธ/initตามค่าเริ่มต้น แต่สามารถแทนที่ได้โดยinit=พารามิเตอร์บรรทัดคำสั่งเคอร์เนล Linux

วิธีที่ยอดเยี่ยมวิธีหนึ่งในการเล่นด้วยinitคือใช้ QEMU เนื่องจากคุณสามารถส่งพารามิเตอร์บรรทัดคำสั่งเคอร์เนลไปยัง QEMU จากบรรทัดคำสั่ง QEMU ด้วย-appendตัวเลือกและไม่ต้องกลัวการเดสก์ท็อปของคุณ

นี่คือการตั้งค่า Buildroot + QEMU แบบอัตโนมัติขนาดเล็กที่สุดของฉันซึ่งทำให้ง่ายต่อการเล่นกับ inits ของคุณเองเพื่ออธิบายปัญหา


0

หากคุณมีความมุ่งมั่นในโมดูลาร์ "ทำสิ่งหนึ่งและทำมันได้ดี" จากนั้นinitโปรแกรมควรเริ่มกระบวนการ

เริ่มกระบวนการ

ควรดำเนินการเมื่อเคอร์เนลประสบความสำเร็จในการคลายบีบอัดดูแลงานพื้นฐานทั้งหมดที่เกี่ยวข้องในการเริ่มต้นกระบวนการเริ่มต้นทั้งหมดที่ระบบต้องการใช้งาน (เช่นการติดตั้งไดรฟ์ที่พบใน / etc / fstab ทำให้อินเทอร์เฟซเครือข่ายและ เป็นต้น)

เนื่องจากกระบวนการของการบูทและปิดระบบนั้นเป็นสิ่งที่ตรงกันข้ามกันโดยทั่วไปมันเป็นเรื่องปกติสำหรับโปรแกรม init เพื่อให้แน่ใจว่ากระบวนการจะหยุดทำงานเมื่อคำสั่งปิดเครื่อง

หยุดกระบวนการ

ซึ่งหมายความว่ามันจะต้องหยุดกระบวนการตาม man page ของกระบวนการนั้น (กล่าวอีกนัยหนึ่งไม่ใช่แค่เพียงโจ่งแจ้งkill -9มันควรทำให้กระบวนการลงไปในแบบที่มันต้องการจะสิ้นสุดลง) ยกเลิกการต่อเชื่อมไดรฟ์และออกคำสั่งพลังงานขั้นสุดท้าย .

อ้างอิง

การอ้างอิงที่ดีสำหรับวิธีการที่ผู้อื่นทำเช่นนี้คือการดูสคริปต์ /etc/rc.d ของ Slackwareและที่ระบบ init แบบง่ายที่มีอยู่แล้วเช่น ninit (ผู้สืบทอดต่อ minit) มีการควบคุมกระบวนการ (หมายถึงหากกระบวนการตายตัวจะถูกเปิดใหม่) ซึ่งไม่ใช่หน้าที่ของ init แต่ก็ยังค่อนข้างพื้นฐานและง่ายต่อการเข้าใจโดยเฉพาะอย่างยิ่งผ่านสคริปต์ตัวอย่างของผู้เขียน

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