พัฒนารหัสเคอร์เนลสำหรับ GKI

อิมเมจเคอร์เนลทั่วไป (GKI) ลดการกระจายตัวของเคอร์เนลด้วยการปรับแนวให้ชิดกัน ด้วยเคอร์เนลของ Linux ต้นทาง แต่ก็มีสาเหตุหลายประการ บางแพตช์ไม่สามารถยอมรับอัปสตรีมได้ และมีกำหนดการของผลิตภัณฑ์ที่ ต้องเป็นไปตามข้อกำหนด ดังนั้นแพตช์บางส่วนจะได้รับการดูแลใน Kernel ทั่วไป (ACK) ของ Android ต้นทางที่ใช้สร้าง GKI

นักพัฒนาซอฟต์แวร์ต้องส่งการเปลี่ยนแปลงโค้ดจากอัปสตรีมโดยใช้ Linux Kernel Mailing ระบุ (LKML) เป็นตัวเลือกแรก และส่งการเปลี่ยนแปลงโค้ดไปยัง ACK android-mainline Branch เมื่อมีเหตุผลที่ชัดเจนว่าทำไมไม่ใช่อัปสตรีม ที่ใช้ได้ผลดี ตัวอย่างสาเหตุที่เป็นไปได้และวิธีจัดการมีดังนี้

  • ส่งแพตช์ไปยัง LKML แล้ว แต่ยังไม่ได้รับการยอมรับทันเวลาสําหรับผลิตภัณฑ์ วิธีจัดการแพตช์นี้

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

  • แพตช์ไม่ได้กว้างพอสำหรับอัปสตรีม และไม่มีเวลาที่จะ เปลี่ยนโครงสร้างภายในโค้ดก่อนเปิดตัวผลิตภัณฑ์ หากต้องการจัดการแพตช์นี้ ให้ระบุ เวลาโดยประมาณในการส่งแพตช์ที่เปลี่ยนโครงสร้างภายในใหม่ (ขั้นตอน แพตช์จะไม่ได้รับการยอมรับใน ACK หากไม่มีแผนที่จะส่งการเปลี่ยนโครงสร้างภายในโค้ด แพตช์จากอัปสตรีมเพื่อตรวจสอบ)

  • อัปสตรีมไม่ยอมรับแพตช์เนื่องจาก... <แทรกเหตุผล ที่นี่> หากต้องการจัดการแพตช์นี้ โปรดติดต่อทีมเคอร์เนลของ Android และ ร่วมมือกับเราเกี่ยวกับตัวเลือกในการเปลี่ยนโครงสร้างภายในโค้ดเพื่อให้ส่งแพตช์ได้ สำหรับการตรวจสอบและอัปสตรีมที่ยอมรับ

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

ข้อกำหนดแพตช์

แพตช์ต้องสอดคล้องกับมาตรฐานการเขียนโค้ดเคอร์เนลของ Linux ที่อธิบายไว้ใน แผนผังแหล่งที่มา Linux ไม่ว่าจะเป็นการส่งอัปสตรีมหรือ 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 ก่อนเพื่อตรวจสอบอัปสตรีม หากแพตช์มีลักษณะดังต่อไปนี้

  • อัปสตรีมที่ยอมรับ จะรวมเป็น android-mainline โดยอัตโนมัติ
  • ไม่ยอมรับอัปสตรีม โปรดส่งไปยัง android-mainline ด้วย การอ้างอิงถึงการส่งอัปสตรีมหรือคําอธิบายสาเหตุที่ไม่ถูกต้อง ส่งไปยัง LKML

หลังจากยอมรับแพตช์จากอัปสตรีมหรือใน android-mainline แพตช์ดังกล่าวสามารถเป็นได้ พอร์ตไปยัง ACK ที่เหมาะสมตาม LTS (เช่น android12-5.4 และ android11-5.4 สำหรับแพตช์ที่แก้ไขรหัสเฉพาะของ Android) กำลังส่งไปยัง android-mainline เปิดการทดสอบกับตัวเลือกการเผยแพร่อัปสตรีมใหม่และ รับประกันว่าแพตช์นั้นอยู่ใน ACK ถัดไปที่ใช้ LTS ข้อยกเว้นรวมถึงกรณีต่างๆ ที่แพตช์อัปสตรีมถูกแบ็คพอร์ตไปยัง android12-5.4 (เนื่องจากแพตช์นี้ ที่มีแนวโน้มว่าจะเป็น android-mainline อยู่แล้ว)

แพตช์อัปสตรีม

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

  • UPSTREAM: - แพตช์ที่เลือกมาจาก "android-mainline" มีแนวโน้มที่จะเป็น ยอมรับไว้ใน ACK หากมีกรณีการใช้งานที่สมเหตุสมผล
  • BACKPORT: - แพตช์จากอัปสตรีมที่ไม่คัดสรรมาอย่างดีและไม่ต้องการ การปรับเปลี่ยนยังมีโอกาสได้รับการยอมรับหากมีการใช้งานที่สมเหตุสมผล
  • FROMGIT: - แพตช์ที่เลือกสรรมาจากสาขาผู้ดูแลที่กำลังเตรียม สำหรับการส่งไปยัง Linux Mainline อาจได้รับการยอมรับหากมี ทั้ง 2 อย่างนี้ต้องรองรับทั้งเนื้อหาและกำหนดการ
  • FROMLIST: - แพตช์ที่ส่งไปยัง LKML แต่ยังไม่ได้ส่ง แต่ไม่ได้รับการยอมรับในสาขาที่มีการบำรุงรักษา เว้นแต่ เหตุผลรองรับมีน้ำหนักเพียงพอที่แพตช์จะได้รับการยอมรับ เครื่องจะเข้าสู่อัปสตรีม Linux หรือไม่ (เราคิดว่าจะไม่) เรียบร้อย ต้องเป็นปัญหาที่เกี่ยวข้องกับแพตช์ FROMLIST เพื่ออำนวยความสะดวกในการสนทนา กับทีมเคอร์เนลของ Android

แพตช์เฉพาะสำหรับ Android

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

การเปลี่ยนแปลง gki_defconfig

การเปลี่ยนแปลง CONFIG ทั้งหมดที่ทำกับ gki_defconfig ต้องมีผลกับทั้ง ARM64 และ เวอร์ชัน x86 เว้นแต่ CONFIG มีไว้สำหรับสถาปัตยกรรมโดยเฉพาะ วิธีส่งคำขอเปลี่ยนแปลง เป็น CONFIG ให้สร้างปัญหาในฝ่ายไอทีเพื่อพูดคุยเรื่องการเปลี่ยนแปลง ช่วง การเปลี่ยนแปลง CONFIG ที่มีผลต่ออินเทอร์เฟซโมดูลเคอร์เนล (KMI) หลังจากพ้นช่วง ตรึง ถูกปฏิเสธ ในกรณีที่พาร์ทเนอร์ส่งคำขอที่ขัดแย้งกัน สำหรับการกำหนดค่าเดียวได้ เราจะดำเนินการแก้ไขข้อขัดแย้งผ่านการพูดคุย ข้อบกพร่องที่เกี่ยวข้อง

รหัสที่ไม่มีอัปสตรีม

การแก้ไขโค้ดที่มีเฉพาะ Android อยู่แล้วจะส่งอัปสตรีมไม่ได้ ตัวอย่างเช่น แม้ว่าไดรเวอร์ Binder จะได้รับการบำรุงรักษาอัปสตรีม แต่การแก้ไข จะไม่สามารถส่งอัปสตรีมให้กับฟีเจอร์การรับค่าลำดับความสำคัญของไดรเวอร์ Binder ได้ เพราะมีไว้สำหรับ Android โดยเฉพาะ ระบุในข้อบกพร่องอย่างชัดเจนและแก้ไขว่าทำไม ส่งจากอัปสตรีมไม่ได้ หากเป็นไปได้ ให้แบ่งแพตช์ออกเป็นส่วนย่อยๆ สามารถส่งอัปสตรีมและชิ้นส่วนเฉพาะสำหรับ Android ที่ส่งไม่ได้ อัปสตรีม เพื่อลดจำนวนโค้ดแบบนอกโครงสร้างที่เก็บรักษาไว้ใน ACK

การเปลี่ยนแปลงอื่นๆ ในหมวดหมู่นี้คือการอัปเดตไฟล์ตัวแทน KMI, KMI รายการสัญลักษณ์, gki_defconfig, สคริปต์บิลด์หรือการกำหนดค่า หรือสคริปต์อื่นๆ ที่ไม่มีอัปสตรีม

โมดูลนอกโครงสร้าง

Upstream Linux ไม่สนับสนุนการสร้างโมดูลนอกโครงสร้างอย่างเต็มที่ นี่เป็นเหตุผลที่สมเหตุสมผลเนื่องจากผู้ดูแล Linux ไม่มีการรับประกัน เกี่ยวกับแหล่งที่มาในเคอร์เนลหรือความเข้ากันได้ของไบนารี และไม่ต้องการรองรับโค้ด ที่ไม่ได้อยู่ในต้นไม้ อย่างไรก็ตาม GKI ให้การรับประกัน ABI สำหรับ โมดูลของผู้จำหน่าย เพื่อให้มั่นใจว่าอินเทอร์เฟซ KMI มีความเสถียรสำหรับ ตลอดอายุการใช้งานของเคอร์เนล ดังนั้นจึงต้องมีการเปลี่ยนแปลงจากผู้ให้บริการสนับสนุนหลายระดับ โมดูลที่ยอมรับสำหรับ ACK แต่ไม่ยอมรับสำหรับอัปสตรีม

ตัวอย่างเช่น ลองพิจารณาแพตช์ที่เพิ่มมาโคร 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 จะยอมรับฮุกของผู้ให้บริการที่อนุญาตให้เรียกใช้โมดูลได้ จากรหัสเคอร์เนลหลัก นอกจากนี้ คุณสามารถเสริมความแข็งแกร่งให้กับโครงสร้างข้อมูลหลัก ฟิลด์ข้อมูลผู้ให้บริการที่พร้อมสำหรับการจัดเก็บข้อมูลเฉพาะผู้ให้บริการเพื่อนำไปใช้ ฟีเจอร์เหล่านี้

ฮุกของผู้ให้บริการมี 2 ตัวแปร (ปกติและแบบจำกัด) ที่อิงจาก จุดติดตาม (ไม่ใช่การติดตามเหตุการณ์) ที่โมดูลของผู้ให้บริการสามารถแนบได้ ตัวอย่างเช่น แทนที่จะเพิ่มฟังก์ชัน sched_exit() ใหม่เพื่อทำบัญชีในงาน ผู้ให้บริการจะสามารถเพิ่มฮุกใน do_exit() ที่โมดูลของผู้ให้บริการนำไปติดได้ เพื่อประมวลผล ตัวอย่างการใช้งานรวมถึงฮุกของผู้ให้บริการต่อไปนี้

  • ฮุกของผู้ให้บริการปกติใช้ DECLARE_HOOK() เพื่อสร้างฟังก์ชันจุดติดตาม ด้วยชื่อ trace_name โดยที่ name คือตัวระบุที่ไม่ซ้ำสำหรับ การติดตาม โดยปกติ ชื่อฮุกผู้ให้บริการปกติจะขึ้นต้นด้วย android_vh ดังนั้น ชื่อสำหรับฮุก sched_exit() จะเป็น android_vh_sched_exit
  • ต้องใช้ฮุกของผู้ให้บริการที่ถูกจำกัดสำหรับกรณีต่างๆ เช่น ฮุกของเครื่องจัดตารางเวลาที่ ต้องเรียกใช้ฟังก์ชันที่แนบแม้ว่า CPU จะออฟไลน์หรือต้องใช้ ซึ่งเป็นบริบทที่ไม่ใช่อะตอม ไม่สามารถถอดฮุกของผู้ให้บริการที่ถูกจำกัดออกได้ ดังนั้นโมดูล ที่ติดอยู่กับฮุกที่จำกัดจะยกเลิกการโหลดไม่ได้ ถูกจำกัด ชื่อฮุกของผู้ให้บริการขึ้นต้นด้วย android_rvh

ในการเพิ่มฮุกผู้ให้บริการ ให้แจ้งปัญหาในฝ่ายไอทีและส่งแพตช์ (เช่นเดียวกับ แพตช์เฉพาะสำหรับ Android ต้องมีปัญหาอยู่ และคุณต้องระบุ เหตุผล) การรองรับ Hook ของผู้ให้บริการจะอยู่ใน ACK เท่านั้น จึงไม่จำเป็นต้องส่ง ไปยังอัปสตรีม Linux

เพิ่มช่องผู้ให้บริการลงในโครงสร้าง

คุณสามารถเชื่อมโยงข้อมูลผู้ให้บริการกับโครงสร้างข้อมูลสำคัญได้โดยการเพิ่ม android_vendor_data ฟิลด์ที่ใช้มาโคร ANDROID_VENDOR_DATA() สำหรับ ตัวอย่างเช่น เพื่อรองรับคุณลักษณะที่เพิ่มคุณค่า ให้ใส่ช่องต่อท้ายโครงสร้างตามที่แสดง ในตัวอย่างโค้ดต่อไปนี้

เพื่อหลีกเลี่ยงความขัดแย้งที่อาจเกิดขึ้นระหว่างฟิลด์ที่ผู้ให้บริการและช่องจำเป็นต้องใช้ OEM ต้องการ OEM ต้องไม่ใช้ช่องที่ประกาศโดยใช้ มาโคร ANDROID_VENDOR_DATA() รายการ 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>

หากต้องการสร้างอินสแตนซ์อินเทอร์เฟซที่จำเป็นสำหรับฮุกของผู้ให้บริการ ให้เพิ่มไฟล์ส่วนหัว ที่มีการประกาศ Hook ไปยัง drivers/android/vendor_hooks.c และส่งออก สัญลักษณ์ ตัวอย่างเช่น โค้ดต่อไปนี้จะทำให้การประกาศ ฮุก android_vh_sched_exit()

#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 มิฉะนั้นจะไม่ปลอดภัย ลดการอ้างอิงตัวชี้ทึบแสงหรือใช้โครงสร้างในบริบทที่มีขนาด การรวม ซึ่งบอกคำจำกัดความที่สมบูรณ์ของโครงสร้างข้อมูลดังกล่าวควรอยู่ภายใน ส่วน #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);
    ...
}

ใช้ฮุกของผู้ให้บริการจากไฟล์ส่วนหัว

คุณอาจต้องอัปเดต Hook ของผู้ให้บริการเพื่อใช้ฮุกของผู้ให้บริการจากไฟล์ส่วนหัว ไฟล์ส่วนหัวที่จะยกเลิกการกำหนด 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.

ในการแก้ไขข้อผิดพลาดของบิลด์ประเภทนี้ ให้ใช้การแก้ไขที่เทียบเท่ากับฮุกของผู้ให้บริการ ไฟล์ส่วนหัวที่รวมอยู่ ดูข้อมูลเพิ่มเติมได้ที่ 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) เพื่อเริ่มการสนทนา

Application Programming Interface (UAPI)

  • ไฟล์ส่วนหัว UAPI การเปลี่ยนแปลงเป็น ไฟล์ส่วนหัว UAPI ต้องเกิดขึ้นอัปสตรีม เว้นแต่ว่าการเปลี่ยนแปลงจะทำกับอินเทอร์เฟซเฉพาะสำหรับ Android เท่านั้น ใช้ไฟล์ส่วนหัวเฉพาะผู้ให้บริการเพื่อกำหนดอินเทอร์เฟซ ระหว่างโมดูลของผู้ให้บริการและโค้ดพื้นที่ผู้ใช้ของผู้ให้บริการ
  • ของโหนด Sysfs โปรดอย่าเพิ่มโหนด Sysfs ใหม่ไปยังเคอร์เนล GKI (การเพิ่มดังกล่าว ใช้ได้ในโมดูลผู้ให้บริการเท่านั้น) โหนด Sysfs ที่ใช้โดย SoC- และ ไลบรารีที่รองรับการใช้งานบนอุปกรณ์และโค้ด Java ที่ประกอบขึ้นเป็นเฟรมเวิร์ก Android เปลี่ยนได้เฉพาะในรูปแบบที่เข้ากันได้เท่านั้น และต้องเปลี่ยนอัปสตรีมหาก ไม่ใช่โหนด Sysf ของ Android โดยเฉพาะ คุณสามารถสร้าง โหนด Syfs เฉพาะผู้ให้บริการที่จะใช้โดยพื้นที่ผู้ใช้ของผู้ให้บริการ โดยค่าเริ่มต้น การเข้าถึงโหนด sysfs ตามพื้นที่ผู้ใช้ถูกปฏิเสธโดยใช้ SELinux ขึ้นอยู่กับ ผู้ให้บริการสามารถเพิ่มป้ายกำกับ SELinux ที่เหมาะสมเพื่ออนุญาตการเข้าถึงโดย ของผู้จำหน่ายซอฟต์แวร์
  • โหนด DebugFS โมดูลผู้ให้บริการสามารถกำหนดโหนดใน debugfs สำหรับ แก้ไขข้อบกพร่องเท่านั้น (เนื่องจากไม่ได้ต่อเชื่อม debugfs ในระหว่างการทํางานปกติของ อุปกรณ์)