ในซอร์สโค้ดเคอร์เนล Linux ฉันพบฟังก์ชันนี้:
static int __init clk_disable_unused(void)
{
// some code
}
ที่นี่ฉันไม่เข้าใจว่า__init
หมายถึงอะไร
ในซอร์สโค้ดเคอร์เนล Linux ฉันพบฟังก์ชันนี้:
static int __init clk_disable_unused(void)
{
// some code
}
ที่นี่ฉันไม่เข้าใจว่า__init
หมายถึงอะไร
คำตอบ:
include/linux/init.h
/* These macros are used to mark some functions or
* initialized data (doesn't apply to uninitialized data)
* as `initialization' functions. The kernel can take this
* as hint that the function is used only during the initialization
* phase and free up used memory resources after
*
* Usage:
* For functions:
*
* You should add __init immediately before the function name, like:
*
* static void __init initme(int x, int y)
* {
* extern int z; z = x * y;
* }
*
* If the function has a prototype somewhere, you can also add
* __init between closing brace of the prototype and semicolon:
*
* extern int initialize_foobar_device(int, int, int) __init;
*
* For initialized data:
* You should insert __initdata between the variable name and equal
* sign followed by value, e.g.:
*
* static int init_variable __initdata = 0;
* static const char linux_logo[] __initconst = { 0x32, 0x36, ... };
*
* Don't forget to initialize data not at file scope, i.e. within a function,
* as gcc otherwise puts the data into the bss section and not into the init
* section.
*
* Also note, that this data cannot be "const".
*/
/* These are for everybody (although not all archs will actually
discard it in modules) */
#define __init __section(.init.text) __cold notrace
#define __initdata __section(.init.data)
#define __initconst __section(.init.rodata)
#define __exitdata __section(.exit.data)
#define __exit_call __used __section(.exitcall.exit)
นี่เป็นเพียงมาโครเพื่อค้นหาบางส่วนของโค้ดลินุกซ์ในพื้นที่พิเศษในไบนารีการรันขั้นสุดท้าย
__init
ตัวอย่างเช่น (หรือดีกว่าที่__attribute__ ((__section__
(".init.text")))
มาโครนี้จะขยายเป็น) สั่งให้คอมไพเลอร์ทำเครื่องหมายฟังก์ชันนี้ด้วยวิธีพิเศษ ในตอนท้ายตัวเชื่อมโยงจะรวบรวมฟังก์ชันทั้งหมดด้วยเครื่องหมายนี้ที่ท้าย (หรือจุดเริ่มต้น) ของไฟล์ไบนารี
เมื่อเคอร์เนลเริ่มทำงานรหัสนี้จะทำงานเพียงครั้งเดียว (การเริ่มต้น) หลังจากรันเคอร์เนลสามารถเพิ่มหน่วยความจำนี้เพื่อนำกลับมาใช้ใหม่ได้และคุณจะเห็นข้อความเคอร์เนล:
การปลดปล่อยหน่วยความจำเคอร์เนลที่ไม่ได้ใช้: ปลดปล่อย 108k
ในการใช้คุณสมบัตินี้คุณต้องมีไฟล์สคริปต์ตัวลิงก์พิเศษซึ่งจะบอกผู้เชื่อมโยงว่าจะค้นหาฟังก์ชันที่ทำเครื่องหมายไว้ทั้งหมดที่ใด
สิ่งนี้แสดงให้เห็นถึงคุณลักษณะของเคอร์เนล 2.2 และใหม่กว่า สังเกตการเปลี่ยนแปลงคำจำกัดความของฟังก์ชันinit
และ แมโครทำให้ฟังก์ชั่นที่จะยกเลิกและหน่วยความจำอิสระเมื่อเสร็จสิ้นการฟังก์ชั่นในตัวคนขับรถ แต่ไม่โมดูลที่ใส่ หากคุณคิดถึงเวลาที่เรียกใช้ฟังก์ชันนี้ก็สมเหตุสมผลดีcleanup
__init
init
init
init
__init เป็นมาโครที่กำหนดใน. /include/linux/init.h ซึ่งขยายเป็น__attribute__ ((__section__(".init.text")))
.
มันสั่งให้คอมไพเลอร์ทำเครื่องหมายฟังก์ชันนี้ด้วยวิธีพิเศษ ในตอนท้ายตัวเชื่อมโยงจะรวบรวมฟังก์ชันทั้งหมดด้วยเครื่องหมายนี้ที่ท้าย (หรือเริ่มต้น) ของไฟล์ไบนารี เมื่อเคอร์เนลเริ่มทำงานรหัสนี้จะทำงานเพียงครั้งเดียว (การเริ่มต้น) หลังจากรันเคอร์เนลสามารถปลดปล่อยหน่วยความจำนี้เพื่อนำกลับมาใช้ใหม่และคุณจะเห็นเคอร์เนล
อ่านความคิดเห็น (และเอกสารในเวลาเดียวกัน) ในลินุกซ์ / init.h
คุณควรทราบด้วยว่า gcc มีส่วนขยายบางอย่างที่สร้างขึ้นเป็นพิเศษสำหรับโค้ดเคอร์เนล linux และดูเหมือนว่ามาโครนี้จะใช้หนึ่งในนั้น
เมื่อคุณคอมไพล์และแทรกโมดูลเคอร์เนลลินุกซ์ลงในเคอร์เนลฟังก์ชันแรกที่จะเรียกใช้คือ __init โดยทั่วไปแล้วฟังก์ชันนี้จะใช้ในการเริ่มต้นก่อนที่คุณจะดำเนินการหลักเช่นการลงทะเบียนไดรเวอร์อุปกรณ์เป็นต้นมีฟังก์ชันอื่นที่มีผลตรงกันข้าม __exit ซึ่งถูกเรียกเมื่อคุณลบโมดูลเคอร์เนลซึ่งใช้อีกครั้งเพื่อลบอุปกรณ์ที่ลงทะเบียนบางส่วนหรือฟังก์ชันที่คล้ายคลึงกันดังกล่าว