รูปภาพเคอร์เนลทั่วไป (GKI) จะลดการกระจัดกระจายของเคิร์นัลโดยการปรับให้สอดคล้องกับเคอร์เนล Linux เวอร์ชันที่พัฒนาขึ้น อย่างไรก็ตาม มีเหตุผลหลายประการที่ทำให้แพตช์เหล่านี้ไม่ได้รับการยอมรับจากอัปสตรีม รวมถึงมีกำหนดการของผลิตภัณฑ์ที่ต้องปฏิบัติตาม ดังนั้นจึงมีการบำรุงรักษาแพตช์บางแพตช์ในแหล่งที่มา Kernel Common (ACK) ของ Android ที่สร้าง GKI
นักพัฒนาซอฟต์แวร์ต้องส่งการเปลี่ยนแปลงโค้ดไปยัง upstream โดยใช้ Linux Kernel Mailing List (LKML) เป็นตัวเลือกแรก และส่งการเปลี่ยนแปลงโค้ดไปยังสาขา ACKandroid-mainline
เฉพาะในกรณีที่มีเหตุผลอันสมควรที่ upstream ไม่เหมาะ ตัวอย่างสาเหตุที่เป็นไปได้และวิธีจัดการมีดังนี้
ส่งแพตช์ไปยัง LKML แล้ว แต่ไม่ได้รับการยอมรับภายในเวลาเปิดตัวผลิตภัณฑ์ วิธีจัดการแพตช์นี้
- แสดงหลักฐานว่ามีการส่งแพตช์ไปยัง LKML และความคิดเห็นที่ได้รับสำหรับแพตช์ หรือเวลาโดยประมาณที่ระบบส่งแพตช์ไปยังอัปสตรีม
- ตัดสินใจเลือกแนวทางในการเผยแพร่แพตช์ใน ACK, ขออนุมัติจากฝั่งอัปสตรีม แล้วนำแพตช์ออกจาก ACK เมื่อผสานเวอร์ชันอัปสตรีมขั้นสุดท้ายลงใน ACK
แพตช์กำหนด
EXPORT_SYMBOLS_GPL()
สำหรับโมดูลของผู้ให้บริการ แต่ส่งไปยังอัปสตรีมไม่ได้เนื่องจากไม่มีโมดูลในต้นไม้ที่ใช้สัญลักษณ์ดังกล่าว หากต้องการจัดการกับแพตช์นี้ โปรดระบุรายละเอียดว่าเหตุใดโมดูลของคุณจึงส่งไปยังระบบส่วนกลางไม่ได้ และทางเลือกอื่นๆ ที่คุณพิจารณาก่อนที่จะส่งคำขอนี้แพตช์ไม่เหมาะสําหรับเวอร์ชันที่อัปเดตจากเวอร์ชันหลักมากพอและไม่มีเวลาที่จะเขียนโค้ดใหม่ก่อนการเปิดตัวผลิตภัณฑ์ ในการจัดการแพตช์นี้ โปรดระบุเวลาโดยประมาณในการส่งอัปสตรีมของแพตช์แบบเปลี่ยนโครงสร้างภายในโค้ด (จะไม่ยอมรับแพตช์ใน ACK หากไม่มีแผนที่จะส่งอัปสตรีมของแพตช์ที่ปรับเปลี่ยนโครงสร้างใหม่เพื่อรับการตรวจสอบ)
อัปสตรีมไม่ยอมรับแพตช์เนื่องจาก... <insert reason here> หากต้องการจัดการกับแพตช์นี้ โปรดติดต่อทีมเคอร์เนล Android และทำงานร่วมกับเราเกี่ยวกับตัวเลือกในการรีแฟกทอเรียลแพตช์เพื่อให้ส่งเข้ารับการตรวจสอบและยอมรับในอัปสตรีมได้
ยังมีเหตุผลอื่นๆ อีกมากมายที่เป็นไปได้ เมื่อส่งข้อบกพร่องหรือแพตช์ ให้ระบุเหตุผลที่ถูกต้องและเตรียมพร้อมที่จะต้องมีการแก้ไขและพูดคุยกัน เราตระหนักดีว่า ACK มีแพตช์บางส่วน โดยเฉพาะในระยะเริ่มต้นของ GKI ขณะที่ทุกคนกำลังเรียนรู้วิธีทํางานกับเวอร์ชันที่อัปเดตอยู่ แต่ไม่สามารถผ่อนปรนกำหนดการของผลิตภัณฑ์เพื่อทําเช่นนั้นได้ โปรดทราบว่าข้อกําหนดในการอัปเดตเวอร์ชันจะเข้มงวดมากขึ้นเมื่อเวลาผ่านไป
ข้อกำหนดแพตช์
แพตช์ต้องเป็นไปตามมาตรฐานการเขียนโค้ดเคอร์เนล Linux ที่อธิบายไว้ในซอร์สทรี Linux ไม่ว่าจะส่งไปยัง upstream หรือ ACK ระบบจะเรียกใช้สคริปต์ scripts/checkpatch.pl
เป็นส่วนหนึ่งของการทดสอบก่อนส่งของ Gerrit ดังนั้นให้เรียกใช้ล่วงหน้าเพื่อให้แน่ใจว่าสคริปต์ทำงานได้ หากต้องการเรียกใช้สคริปต์ checkpatch ที่มีการกำหนดค่าเดียวกับการทดสอบก่อนส่ง ให้ใช้ //build/kernel/static_analysis:checkpatch_presubmit
ดูรายละเอียดได้ที่
build/kernel/kleaf/docs/checkpatch.md
แพตช์ ACK
แพตช์ที่ส่งไปยัง ACK ต้องเป็นไปตามมาตรฐานการเขียนโค้ดเคอร์เนล Linux และหลักเกณฑ์การมีส่วนร่วม
คุณต้องใส่แท็ก Change-Id
ในข้อความคอมมิต หากคุณส่งแพตช์ไปยังหลายสาขา (เช่น android-mainline
และ android12-5.4
) คุณต้องใช้ Change-Id
เดียวกันกับอินสแตนซ์ทั้งหมดของแพตช์
ส่งแพตช์ไปยัง LKML ก่อนเพื่อรับการตรวจสอบจาก upstream หากแพตช์มีลักษณะดังต่อไปนี้
- อัปสตรีมที่ยอมรับ ระบบจะผสานรวมเป็น
android-mainline
โดยอัตโนมัติ - ไม่ยอมรับใน upstream ให้ส่งไปยัง
android-mainline
พร้อมการอ้างอิงถึงการส่งใน upstream หรือคำอธิบายสาเหตุที่ไม่ได้ส่งไปยัง LKML
หลังจากยอมรับแพตช์ในอัปสตรีมหรือใน android-mainline
แล้ว คุณสามารถพอร์ตแพตช์ไปยัง ACK ที่ใช้ LTS ที่เหมาะสม (เช่น android12-5.4
และ android11-5.4
สำหรับแพตช์ที่แก้ไขโค้ดเฉพาะ Android) การส่งไปยัง android-mainline
จะช่วยให้ทดสอบกับรุ่นที่พร้อมใช้งานใหม่ในอัปสตรีมได้ และรับประกันว่าแพตช์จะอยู่ใน ACK ที่ใช้ LTS รุ่นถัดไป ข้อยกเว้นรวมถึงกรณีที่มีการพอร์ตแพตช์จาก upstream ไปยัง android12-5.4
(เนื่องจากแพตช์มีแนวโน้มที่จะอยู่ใน android-mainline
อยู่แล้ว)
แพตช์อัปสตรีม
ตามที่ระบุไว้ในหลักเกณฑ์การมีส่วนร่วม แพตช์จาก upstream ที่มีไว้สำหรับเคอร์เนล ACK จะแบ่งออกเป็นกลุ่มต่อไปนี้ (เรียงตามลำดับความเป็นไปได้ที่จะได้รับอนุมัติ)
UPSTREAM:
- แพตช์ที่คัดสรรมาอย่างดีจาก "android-mainline" มีแนวโน้มที่จะได้รับยอมรับใน ACK หากมี Use Case ที่สมเหตุสมผลBACKPORT:
- แพตช์จากอัปสตรีมที่ไม่ได้เลือกเฉพาะบางรายการอย่างเรียบร้อยและจำเป็นต้องมีการแก้ไขก็อาจได้รับการยอมรับเช่นกันหากมีกรณีการใช้งานที่เหมาะสมFROMGIT:
- เราอาจยอมรับการแก้ไขที่คัดสรรมาจากสาขาของผู้ดูแลเพื่อเตรียมส่งไปยังสาขาหลักของ Linux หากมีกำหนดเวลาที่จะถึง ทั้ง 2 อย่างนี้ต้องรองรับทั้งเนื้อหาและกำหนดการFROMLIST:
- แพตช์ที่ส่งไปยัง LKML แต่ยังไม่ได้รับการยอมรับในสาขาของผู้ดูแลระบบมีแนวโน้มที่จะไม่ได้รับการยอมรับ เว้นแต่จะมีเหตุผลที่น่าสนใจมากพอที่จะทำให้แพตช์ได้รับการยอมรับ ไม่ว่าจะนำไปใช้ใน Linux เวอร์ชันที่พัฒนาขึ้นร่วมกันหรือไม่ก็ตาม (เราถือว่าจะไม่นำไปใช้) ปัญหาต้องเกี่ยวข้องกับแพตช์FROMLIST
เพื่อให้เราพูดคุยกับทีมเคอร์เนล Android ได้
แพตช์สำหรับ Android โดยเฉพาะ
หากทําการเปลี่ยนแปลงที่จําเป็นในอัปสตรีมไม่ได้ ให้ลองส่งแพตช์ที่ไม่ใช่ของต้นไม้ไปยัง ACK โดยตรง การส่งแพตช์ที่ไม่ใช่ในต้นไม้กำหนดให้คุณสร้างปัญหาในทีมไอทีซึ่งอ้างอิงถึงแพตช์และเหตุผลที่ส่งแพตช์ไปยังเวอร์ชันที่ใช้งานจริงไม่ได้ (ดูตัวอย่างในรายการก่อนหน้า)
อย่างไรก็ตาม อาจมีบางกรณีที่ส่งโค้ดไปยังระบบส่วนกลางไม่ได้ กรณีเหล่านี้จะครอบคลุมดังต่อไปนี้ และต้องเป็นไปตามหลักเกณฑ์การมีส่วนร่วมสำหรับแพตช์เฉพาะ Android และติดแท็กด้วยคำนำหน้า ANDROID:
ในเรื่อง
การเปลี่ยนแปลง gki_defconfig
การเปลี่ยนแปลง CONFIG
ทั้งหมดใน gki_defconfig
มีผลกับทั้งเวอร์ชัน arm64 และ x86 เว้นแต่ว่า CONFIG
จะเป็นเฉพาะสำหรับสถาปัตยกรรม หากต้องการขอเปลี่ยนแปลงการตั้งค่า CONFIG
ให้สร้างปัญหาในทีมไอทีเพื่อพูดคุยเกี่ยวกับการเปลี่ยนแปลง ระบบจะปฏิเสธCONFIG
การเปลี่ยนแปลงที่ส่งผลต่ออินเทอร์เฟซของโมดูลเคอร์เนล (KMI) หลังจากที่มีการหยุด ในกรณีที่พาร์ทเนอร์ขอการตั้งค่าที่ขัดแย้งกันสำหรับการกำหนดค่าเดียว เราจะแก้ไขข้อขัดแย้งผ่านการพูดคุยถึงข้อบกพร่องที่เกี่ยวข้อง
โค้ดที่ไม่มีอยู่ในส่วนที่ส่งผ่านข้อมูล
คุณจะส่งการแก้ไขโค้ดที่เจาะจง Android อยู่แล้วไปยัง upstream ไม่ได้ ตัวอย่างเช่น แม้ว่าจะมีการบำรุงรักษาไดรเวอร์ Binder ในอัปสตรีม แต่คุณจะส่งการแก้ไขฟีเจอร์การสืบทอดลําดับความสําคัญของไดรเวอร์ Binder ไปยังอัปสตรีมไม่ได้เนื่องจากฟีเจอร์ดังกล่าวมีไว้สําหรับ Android โดยเฉพาะ ระบุข้อบกพร่องและแพตช์อย่างชัดเจนว่าเหตุใดจึงส่งโค้ดไปยัง upstream ไม่ได้ หากเป็นไปได้ ให้แยกแพตช์ออกเป็นส่วนๆ ที่ส่งไปยัง upstream ได้ และส่วนสำหรับ Android โดยเฉพาะที่ส่งไปยัง upstream ไม่ได้ เพื่อลดจำนวนโค้ดนอกต้นไม้ที่ดูแลรักษาใน ACK
การเปลี่ยนแปลงอื่นๆ ในหมวดหมู่นี้ ได้แก่ การอัปเดตไฟล์การนำเสนอ KMI, รายการสัญลักษณ์ KMI, gki_defconfig
, สคริปต์การสร้างหรือการกำหนดค่า หรือสคริปต์อื่นๆ ที่ไม่มีอยู่ในส่วนต้น
โมดูลนอกโครงสร้าง
Upstream Linux ไม่สนับสนุนการสร้างโมดูลนอกโครงสร้างอย่างเต็มที่ นี่เป็นแนวทางที่สมเหตุสมผลเนื่องจากผู้ดูแลระบบ Linux ไม่ได้รับประกันเกี่ยวกับซอร์สโค้ดในเคอร์เนลหรือความเข้ากันได้ของไบนารี และไม่ต้องการรองรับโค้ดที่ไม่ได้อยู่ในต้นไม้ อย่างไรก็ตาม GKI รับประกัน ABI สำหรับข้อบังคับของโมดูลของผู้ให้บริการ เพื่อให้อินเทอร์เฟซ KMI ทำงานได้อย่างเสถียรตลอดอายุการใช้งานของเคอร์เนลที่รองรับ ดังนั้นจึงมีคลาสการเปลี่ยนแปลงเพื่อรองรับข้อบังคับของผู้ให้บริการซึ่งยอมรับได้สำหรับ ACK แต่ไม่ยอมรับสำหรับ Upstream
ตัวอย่างเช่น ลองพิจารณาแพตช์ที่เพิ่มมาโคร EXPORT_SYMBOL_GPL()
ในกรณีที่โมดูลที่ใช้การส่งออกไม่ได้อยู่ในสคีมาต้นทาง แม้ว่าคุณจะต้องพยายามขออัปสตรีม EXPORT_SYMBOL_GPL()
และจัดหาโมดูลที่ใช้สัญลักษณ์ที่ส่งออกใหม่ แต่หากมีเหตุผลที่ชัดเจนว่าเหตุใดจึงไม่ส่งโมดูลดังกล่าวไปยังอัปสตรีม คุณส่งแพตช์ไปยัง ACK แทนได้ คุณต้องระบุเหตุผลที่อัปสตรีมโมดูลไม่ได้ในปัญหา (อย่าขอตัวแปรที่ไม่ใช่ GPL EXPORT_SYMBOL()
)
การกําหนดค่าที่ซ่อนอยู่
โมดูลในแผนผังบางโมดูลจะเลือกการกำหนดค่าที่ซ่อนอยู่ซึ่งไม่สามารถระบุได้ใน gki_defconfig
โดยอัตโนมัติ เช่น ระบบจะเลือก CONFIG_SND_SOC_TOPOLOGY
โดยอัตโนมัติเมื่อกําหนดค่า CONFIG_SND_SOC_SOF=y
GKI มีกลไกในการเปิดใช้การกำหนดค่าที่ซ่อนอยู่เพื่อรองรับการสร้างโมดูลนอกต้นไม้
หากต้องการเปิดใช้การกำหนดค่าที่ซ่อนอยู่ ให้เพิ่มคำสั่ง select
ใน init/Kconfig.gki
เพื่อให้ระบบเลือกการกำหนดค่าดังกล่าวโดยอัตโนมัติตามการกำหนดค่าเคอร์เนลของ CONFIG_GKI_HACKS_TO_FIX
ซึ่งเปิดใช้อยู่ใน gki_defconfig
ใช้กลไกนี้สำหรับการกำหนดค่าที่ซ่อนอยู่เท่านั้น หากไม่ได้ซ่อนการกำหนดค่าไว้ คุณจะต้องระบุการกำหนดค่าใน gki_defconfig
อย่างชัดแจ้งหรือเป็นทรัพยากร Dependency
ตัวควบคุมที่สามารถโหลดได้
สำหรับเฟรมเวิร์กเคอร์เนล (เช่น cpufreq
) ที่รองรับตัวควบคุมโหลดได้ คุณสามารถลบล้างตัวควบคุมเริ่มต้น (เช่น ตัวควบคุม schedutil
ของ cpufreq
) สำหรับเฟรมเวิร์ก (เช่น เฟรมเวิร์กด้านความร้อน) ที่ไม่รองรับตัวควบคุมหรือไดรเวอร์ที่โหลดได้ แต่ยังคงต้องใช้การติดตั้งเฉพาะของผู้ให้บริการ ให้สร้างปัญหาในทีมไอทีและปรึกษากับทีมเคอร์เนล Android
เราจะทำงานร่วมกับคุณและผู้ดูแลระบบในอัปสตรีมเพื่อเพิ่มการสนับสนุนที่จำเป็น
ฮุกของผู้ให้บริการ
ในรุ่นที่ผ่านมา คุณสามารถเพิ่มการแก้ไขเฉพาะของผู้ให้บริการลงในเคอร์เนลหลักได้โดยตรง ซึ่งไม่สามารถทำได้ใน GKI 2.0 เนื่องจากต้องติดตั้งใช้งานโค้ดเฉพาะผลิตภัณฑ์ในโมดูลและระบบจะไม่ยอมรับในเคอร์เนลหลักที่ส่งผ่านข้อมูลหรือใน ACK GKI ยอมรับฮุกของผู้ให้บริการที่อนุญาตให้เรียกใช้โมดูลจากโค้ดเคอร์เนลหลัก เพื่อเปิดใช้ฟีเจอร์ที่มีคุณค่าซึ่งพาร์ทเนอร์ต้องใช้โดยส่งผลกระทบต่อโค้ดเคอร์เนลหลักน้อยที่สุด นอกจากนี้ คุณยังเพิ่มช่องข้อมูลผู้ให้บริการที่พร้อมจัดเก็บข้อมูลเฉพาะของผู้ให้บริการเพื่อใช้ฟีเจอร์เหล่านี้ในโครงสร้างข้อมูลคีย์ได้ด้วย
Hook ของผู้ให้บริการมี 2 ตัวแปร (ปกติและแบบจำกัด) ที่อิงตามจุดติดตาม (ไม่ใช่ติดตามเหตุการณ์) ซึ่งโมดูลของผู้ให้บริการจะต่อเชื่อมได้ ตัวอย่างเช่น แทนที่จะเพิ่มฟังก์ชัน sched_exit()
ใหม่เพื่อทำการบัญชีเมื่อสิ้นสุดการทำงานของงาน ผู้ให้บริการสามารถเพิ่มฮุกใน do_exit()
ที่โมดูลของผู้ให้บริการจะแนบไว้เพื่อประมวลผลได้ ตัวอย่างการติดตั้งใช้งานมีฮุกของผู้ให้บริการต่อไปนี้
- ฮุกของผู้ให้บริการทั่วไปใช้
DECLARE_HOOK()
เพื่อสร้างฟังก์ชันการติดตามที่มีชื่อtrace_name
โดยที่name
คือตัวระบุที่ไม่ซ้ำกันสำหรับการติดตาม ตามธรรมเนียมแล้ว ชื่อฮุกของผู้ให้บริการปกติจะขึ้นต้นด้วยandroid_vh
ดังนั้นชื่อฮุกsched_exit()
จะเป็นandroid_vh_sched_exit
- ต้องใช้ฮุกของผู้ให้บริการที่ถูกจำกัดสำหรับกรณีต่างๆ เช่น ฮุกเครื่องจัดตารางเวลาที่ต้องเรียกใช้ฟังก์ชันที่แนบแม้ว่า CPU จะออฟไลน์อยู่หรือต้องใช้บริบทที่ไม่ใช่แบบอะตอมก็ตาม คุณไม่สามารถถอดฮุกของผู้ให้บริการที่จํากัดออกได้ ดังนั้นโมดูลที่แนบกับฮุกที่จํากัดจะยกเลิกการโหลดไม่ได้ ชื่อฮุกของผู้ให้บริการที่จำกัดจะขึ้นต้นด้วย
android_rvh
หากต้องการเพิ่มฮุกของผู้ให้บริการ ให้ยื่นปัญหาด้านไอทีและส่งแพตช์ (เช่นเดียวกับแพตช์ทั้งหมดเฉพาะสำหรับ Android จะต้องมีปัญหาอยู่และต้องระบุเหตุผล) การรองรับฮุกของผู้ให้บริการมีอยู่ใน ACK เท่านั้น ดังนั้นอย่าส่งแพตช์เหล่านี้ไปยัง Linux เวอร์ชันที่พัฒนาขึ้น
เพิ่มช่องผู้ให้บริการลงในโครงสร้าง
คุณสามารถเชื่อมโยงข้อมูลผู้ให้บริการกับโครงสร้างข้อมูลหลักได้โดยเพิ่มช่อง android_vendor_data
โดยใช้มาโคร ANDROID_VENDOR_DATA()
เช่น หากต้องการรองรับฟีเจอร์ที่มีมูลค่าเพิ่ม ให้เพิ่มช่องต่อท้ายโครงสร้างดังที่แสดงในตัวอย่างโค้ดต่อไปนี้
OEM ต้องไม่ใช้ช่องที่ประกาศโดยใช้มาโคร ANDROID_VENDOR_DATA()
เพื่อหลีกเลี่ยงความขัดแย้งที่อาจเกิดขึ้นระหว่างช่องที่นักพัฒนาแอปต้องการกับช่องที่ OEM ต้องการ แต่ OEM ต้องใช้ ANDROID_OEM_DATA()
เพื่อประกาศฟิลด์ android_oem_data
แทน
#include <linux/android_vendor.h>
...
struct important_kernel_data {
[all the standard fields];
/* Create vendor data for use by hook implementations. The
* size of vendor data is based on vendor input. Vendor data
* can be defined as single u64 fields like the following that
* declares a single u64 field named "android_vendor_data1" :
*/
ANDROID_VENDOR_DATA(1);
/*
* ...or an array can be declared. The following is equivalent to
* u64 android_vendor_data2[20]:
*/
ANDROID_VENDOR_DATA_ARRAY(2, 20);
/*
* SoC vendors must not use fields declared for OEMs and
* OEMs must not use fields declared for SoC vendors.
*/
ANDROID_OEM_DATA(1);
/* no further fields */
}
กำหนดฮุกของผู้ให้บริการ
เพิ่มฮุกของผู้ให้บริการลงในโค้ดเคอร์เนลเป็นจุดการติดตามโดยการประกาศโดยใช้ DECLARE_HOOK()
หรือ DECLARE_RESTRICTED_HOOK()
แล้วเพิ่มลงในโค้ดเป็นจุดติดตาม เช่น หากต้องการเพิ่ม trace_android_vh_sched_exit()
ลงในฟังก์ชันเคอร์เนล do_exit()
ที่มีอยู่ ให้ทำดังนี้
#include <trace/hooks/exit.h>
void do_exit(long code)
{
struct task_struct *tsk = current;
...
trace_android_vh_sched_exit(tsk);
...
}
ฟังก์ชัน trace_android_vh_sched_exit()
จะตรวจสอบเพียงว่ามีสิ่งที่แนบอยู่หรือไม่ในตอนแรก อย่างไรก็ตาม หากโมดูลของผู้ให้บริการลงทะเบียนตัวแฮนเดิลโดยใช้ register_trace_android_vh_sched_exit()
ระบบจะเรียกใช้ฟังก์ชันที่ลงทะเบียนไว้ ตัวแฮนเดิลต้องทราบบริบทเกี่ยวกับล็อกที่ถืออยู่ สถานะ RCS และปัจจัยอื่นๆ คุณต้องกำหนดฮุกในไฟล์ส่วนหัวในไดเรกทอรี include/trace/hooks
ตัวอย่างเช่น โค้ดต่อไปนี้แสดงประกาศที่เป็นไปได้สำหรับ trace_android_vh_sched_exit()
ในไฟล์ include/trace/hooks/exit.h
/* SPDX-License-Identifier: GPL-2.0 */
#undef TRACE_SYSTEM
#define TRACE_SYSTEM sched
#define TRACE_INCLUDE_PATH trace/hooks
#if !defined(_TRACE_HOOK_SCHED_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_HOOK_SCHED_H
#include <trace/hooks/vendor_hooks.h>
/*
* Following tracepoints are not exported in tracefs and provide a
* mechanism for vendor modules to hook and extend functionality
*/
struct task_struct;
DECLARE_HOOK(android_vh_sched_exit,
TP_PROTO(struct task_struct *p),
TP_ARGS(p));
#endif /* _TRACE_HOOK_SCHED_H */
/* This part must be outside protection */
#include <trace/define_trace.h>
หากต้องการสร้างอินเทอร์เฟซที่จําเป็นสําหรับฮุกของผู้ให้บริการ ให้เพิ่มไฟล์ส่วนหัวที่มีการประกาศฮุกลงใน drivers/android/vendor_hooks.c
และส่งออกสัญลักษณ์ ตัวอย่างเช่น โค้ดต่อไปนี้จะประกาศ android_vh_sched_exit()
hook ให้เสร็จสมบูรณ์
#ifndef __GENKSYMS__
/* struct task_struct */
#include <linux/sched.h>
#endif
#define CREATE_TRACE_POINTS
#include <trace/hooks/vendor_hooks.h>
#include <trace/hooks/exit.h>
/*
* Export tracepoints that act as a bare tracehook (i.e. have no trace
* event associated with them) to allow external modules to probe
* them.
*/
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_sched_exit);
หมายเหตุ: โครงสร้างข้อมูลที่ใช้ภายในการประกาศ Hook ต้องได้รับการกำหนดอย่างสมบูรณ์เพื่อรับประกันความเสถียรของ ABI มิฉะนั้น ไม่ปลอดภัยที่จะปิดใช้งานตัวชี้แบบทึบหรือใช้โครงสร้างในบริบทที่มีขนาด ส่วน include ที่ระบุคำจำกัดความของโครงสร้างข้อมูลดังกล่าวอย่างเต็มรูปแบบควรอยู่ภายในส่วน #ifndef __GENKSYMS__
ของ drivers/android/vendor_hooks.c
ไฟล์ส่วนหัวใน include/trace/hooks
ไม่ควรรวมไฟล์ส่วนหัวของเคอร์เนลที่มีคำจำกัดความของประเภทเพื่อหลีกเลี่ยงการเปลี่ยนแปลง CRC ซึ่งจะทำให้ KMI ใช้งานไม่ได้ แต่ให้ประกาศประเภทแบบส่งต่อแทน
แนบกับฮุกของผู้ให้บริการ
หากต้องการใช้ฮุกของผู้ให้บริการ โมดูลผู้ให้บริการจะต้องลงทะเบียนเครื่องจัดการสำหรับฮุก
(โดยปกติจะทำระหว่างการเริ่มต้นโมดูล) เช่น โค้ดต่อไปนี้แสดงเครื่องจัดการ foo.ko
ของโมดูลสำหรับ trace_android_vh_sched_exit()
#include <trace/hooks/sched.h>
...
static void foo_sched_exit_handler(void *data, struct task_struct *p)
{
foo_do_exit_accounting(p);
}
...
static int foo_probe(..)
{
...
rc = register_trace_android_vh_sched_exit(foo_sched_exit_handler, NULL);
...
}
ใช้ฮุกของผู้ให้บริการจากไฟล์ส่วนหัว
หากต้องการใช้ฮุกของผู้ให้บริการจากไฟล์ส่วนหัว คุณอาจต้องอัปเดตไฟล์ส่วนหัวของฮุกของผู้ให้บริการเพื่อยกเลิกการกําหนดค่า TRACE_INCLUDE_PATH
เพื่อหลีกเลี่ยงข้อผิดพลาดในการสร้างที่ระบุว่าไม่พบไฟล์ส่วนหัวของจุดติดตาม ตัวอย่างเช่น
In file included from .../common/init/main.c:111:
In file included from .../common/include/trace/events/initcall.h:74:
.../common/include/trace/define_trace.h:95:10: fatal error: 'trace/hooks/initcall.h' file not found
95 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.../common/include/trace/define_trace.h:90:32: note: expanded from macro 'TRACE_INCLUDE'
90 | # define TRACE_INCLUDE(system) __TRACE_INCLUDE(system)
| ^~~~~~~~~~~~~~~~~~~~~~~
.../common/include/trace/define_trace.h:87:34: note: expanded from macro '__TRACE_INCLUDE'
87 | # define __TRACE_INCLUDE(system) __stringify(TRACE_INCLUDE_PATH/system.h)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.../common/include/linux/stringify.h:10:27: note: expanded from macro '__stringify'
10 | #define __stringify(x...) __stringify_1(x)
| ^~~~~~~~~~~~~~~~
.../common/include/linux/stringify.h:9:29: note: expanded from macro '__stringify_1'
9 | #define __stringify_1(x...) #x
| ^~
<scratch space>:14:1: note: expanded from here
14 | "trace/hooks/initcall.h"
| ^~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
ในการแก้ไขข้อผิดพลาดของบิลด์ประเภทนี้ ให้ใช้การแก้ไขที่เทียบเท่ากับไฟล์ส่วนหัว Hook ของผู้ให้บริการที่คุณกำลังรวม ดูข้อมูลเพิ่มเติมได้ที่ https://r.android.com/3066703
diff --git a/include/trace/hooks/mm.h b/include/trace/hooks/mm.h
index bc6de7e53d66..039926f7701d 100644
--- a/include/trace/hooks/mm.h
+++ b/include/trace/hooks/mm.h
@@ -2,7 +2,10 @@
#undef TRACE_SYSTEM
#define TRACE_SYSTEM mm
+#ifdef CREATE_TRACE_POINTS
#define TRACE_INCLUDE_PATH trace/hooks
+#define UNDEF_TRACE_INCLUDE_PATH
+#endif
การกําหนด UNDEF_TRACE_INCLUDE_PATH
บอก include/trace/define_trace.h
ให้ยกเลิกการกําหนด TRACE_INCLUDE_PATH
หลังจากสร้างจุดติดตาม
ฟีเจอร์หลักของเคิร์นัล
หากเทคนิคก่อนหน้านี้ไม่ช่วยให้คุณใช้ฟีเจอร์จากโมดูลได้ คุณต้องเพิ่มฟีเจอร์ดังกล่าวเป็นการแก้ไขเฉพาะสำหรับ Android ลงในเคอร์เนลหลัก สร้างปัญหาในเครื่องมือติดตามปัญหา (IT) เพื่อเริ่มการสนทนา
User Application Programming Interface (UAPI)
- ไฟล์ส่วนหัว UAPI การเปลี่ยนแปลงไฟล์ส่วนหัว UAPI ต้องเกิดขึ้นที่ต้นทาง เว้นแต่การเปลี่ยนแปลงจะเป็นอินเทอร์เฟซเฉพาะ Android ใช้ไฟล์ส่วนหัวเฉพาะของผู้ให้บริการเพื่อกำหนดอินเทอร์เฟซระหว่างโมดูลของผู้ให้บริการกับโค้ดพื้นที่ผู้ใช้ของผู้ให้บริการ
- โหนด sysfs อย่าเพิ่มโหนด sysfs ใหม่ลงในเคอร์เนล GKI (การเพิ่มดังกล่าวใช้ได้เฉพาะในโมดูลของผู้ให้บริการ) โหนด sysfs ที่ใช้โดยไลบรารีที่ไม่เจาะจง SoC และอุปกรณ์ รวมถึงโค้ด Java ที่ประกอบเฟรมเวิร์ก Android จะเปลี่ยนแปลงได้เฉพาะในลักษณะที่เข้ากันได้ และต้องเปลี่ยนแปลงในฝั่งที่ส่งออกหากไม่ใช่โหนด sysfs สำหรับ Android โดยเฉพาะ คุณสามารถสร้างโหนด sysfs เฉพาะของผู้ให้บริการเพื่อใช้โดยพื้นที่ผู้ใช้ของผู้ให้บริการ โดยค่าเริ่มต้น การเข้าถึงโหนด sysfs ตามพื้นที่ผู้ใช้จะถูกปฏิเสธโดยใช้ SELinux ขึ้นอยู่กับผู้ให้บริการที่จะเพิ่มป้ายกำกับ SELinux ที่เหมาะสมเพื่ออนุญาตให้ซอฟต์แวร์ของผู้ให้บริการที่ได้รับอนุญาตเข้าถึง
- โหนด DebugFS โมดูลของผู้ให้บริการจะกำหนดโหนดใน
debugfs
สำหรับการแก้ไขข้อบกพร่องเท่านั้น (เนื่องจากระบบไม่ได้เมานต์debugfs
ในระหว่างการทํางานปกติของอุปกรณ์)