Có nhiều trường hợp gọi __init trong hạt nhân cả trong trình điều khiển module_init và các hàm khác của hạt nhân. Nghi ngờ của tôi là làm thế nào chính xác hạt nhân xác định trình tự của cuộc gọi __init. Quan trọng hơn, Làm thế nào nó cũng xác định trình tự của trình điều khiển gọi module_init?Cách hạt nhân xác định chuỗi các cuộc gọi __init
Trả lời
Tất cả các init ma thuật được thực hiện trong các tập tin:
Thứ nhất, nhìn vào include/asm-generic/vmlinux.lds.h
chứa following:
13 * . = START;
14 * __init_begin = .;
15 * HEAD_TEXT_SECTION
16 * INIT_TEXT_SECTION(PAGE_SIZE)
17 * INIT_DATA_SECTION(...)
18 * PERCPU_SECTION(CACHELINE_SIZE)
19 * __init_end = .;
đâu INIT_TEXT_SECTION và INIT_DATA_SECTION được xác định như sau:
790 #define INIT_TEXT_SECTION(inittext_align) \
791 . = ALIGN(inittext_align); \
792 .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) { \
793 VMLINUX_SYMBOL(_sinittext) = .; \
794 INIT_TEXT \
795 VMLINUX_SYMBOL(_einittext) = .; \
796 }
797
798 #define INIT_DATA_SECTION(initsetup_align) \
799 .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { \
800 INIT_DATA \
801 INIT_SETUP(initsetup_align) \
802 INIT_CALLS \
803 CON_INITCALL \
804 SECURITY_INITCALL \
805 INIT_RAM_FS \
806 }
Hãy nhìn vào INIT_CALLS định nghĩa ví dụ:
628 #define INIT_CALLS_LEVEL(level) \
629 VMLINUX_SYMBOL(__initcall##level##_start) = .; \
630 *(.initcall##level##.init) \
631 *(.initcall##level##s.init)
633 #define INIT_CALLS \
634 VMLINUX_SYMBOL(__initcall_start) = .; \
635 *(.initcallearly.init) \
636 INIT_CALLS_LEVEL(0) \
637 INIT_CALLS_LEVEL(1) \
638 INIT_CALLS_LEVEL(2) \
639 INIT_CALLS_LEVEL(3) \
640 INIT_CALLS_LEVEL(4) \
641 INIT_CALLS_LEVEL(5) \
642 INIT_CALLS_LEVEL(rootfs) \
643 INIT_CALLS_LEVEL(6) \
644 INIT_CALLS_LEVEL(7) \
645 VMLINUX_SYMBOL(__initcall_end) = .;
Bạn có thể xem này xác định tên phần mà được đánh dấu bằng .initcall...
. Và tất cả dữ liệu được đánh dấu đều nằm trong phạm vi __initcall_start .. __initcall_end
.
Bây giờ chúng ta hãy nhìn vào [include/linux/init.h
chứa following:
44 #define __init __section(.init.text) __cold notrace
45 #define __initdata __section(.init.data)
Và hơn nữa:
189 #define __define_initcall(level,fn,id) \
190 static initcall_t __initcall_##fn##id __used \
191 __attribute__((__section__(".initcall" level ".init"))) = fn
...
220 #define device_initcall(fn) __define_initcall("6",fn,6)
...
225 #define __initcall(fn) device_initcall(fn)
...
271 /**
272 * module_init() - driver initialization entry point
273 * @x: function to be run at kernel boot time or module insertion
274 *
275 * module_init() will either be called during do_initcalls() (if
276 * builtin) or at module insertion time (if a module). There can only
277 * be one per module.
278 */
279 #define module_init(x) __initcall(x);
Vì vậy, bạn có thể thấy rằng module_init
định nghĩa là __initcall
rằng định nghĩa là device_initcall
rằng định nghĩa là __define_initcall("6",fn,6)
. Sáu ở đây có nghĩa là cấp độ initcall. Xem dưới đây ...
init/main.c
chứa following:
711 extern initcall_t __initcall_start[];
712 extern initcall_t __initcall0_start[];
713 extern initcall_t __initcall1_start[];
714 extern initcall_t __initcall2_start[];
715 extern initcall_t __initcall3_start[];
716 extern initcall_t __initcall4_start[];
717 extern initcall_t __initcall5_start[];
718 extern initcall_t __initcall6_start[];
719 extern initcall_t __initcall7_start[];
720 extern initcall_t __initcall_end[];
721
722 static initcall_t *initcall_levels[] __initdata = {
723 __initcall0_start,
724 __initcall1_start,
725 __initcall2_start,
726 __initcall3_start,
727 __initcall4_start,
728 __initcall5_start,
729 __initcall6_start,
730 __initcall7_start,
731 __initcall_end,
732 };
733
734 /* Keep these in sync with initcalls in include/linux/init.h */
735 static char *initcall_level_names[] __initdata = {
736 "early",
737 "core",
738 "postcore",
739 "arch",
740 "subsys",
741 "fs",
742 "device",
743 "late",
744 };
745
746 static void __init do_initcall_level(int level)
747 {
748 extern const struct kernel_param __start___param[], __stop___param[];
749 initcall_t *fn;
750
751 strcpy(static_command_line, saved_command_line);
752 parse_args(initcall_level_names[level],
753 static_command_line, __start___param,
754 __stop___param - __start___param,
755 level, level,
756 &repair_env_string);
757
758 for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)
759 do_one_initcall(*fn);
760 }
761
762 static void __init do_initcalls(void)
763 {
764 int level;
765
766 for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++)
767 do_initcall_level(level);
768 }
Như bạn thấy do_initcall
chỉ đơn giản lặp trên tất cả các cấp initcall và gọi do_initcall_level
cho mỗi người mà các cuộc gọi do_one_initcall cho entry của mỗi cấp độ.
Hãy lưu ý rằng hạt nhân sẽ hủy tất cả các chức năng __init
sau khi thực thi. Vì vậy, chúng không diễn ra trong bộ nhớ sau khi tải hạt nhân.
Đó là tất cả.
- 1. Tạo biểu đồ cuộc gọi tĩnh cho hạt nhân Linux
- 2. __init có nghĩa là gì trong mã hạt nhân Linux?
- 3. Gọi hạt nhân OpenCL từ một hạt nhân OpenCL khác
- 4. Thực hiện các cuộc gọi/bẫy hệ thống trong nguồn hạt nhân Linux
- 5. Chuỗi hạt nhân là gì?
- 6. Các cuộc gọi hạt nhân cuda đồng bộ hoặc không đồng bộ
- 7. Định thời các phần khác nhau trong hạt nhân CUDA
- 8. Cách xác minh hạt nhân được thực hiện trong CUDA
- 9. Tìm kiếm triển khai cuộc gọi hệ thống trên hạt nhân Linux
- 10. Khi nào sử dụng các chuỗi hạt nhân vs các giá trị gia công trong hạt nhân Linux
- 11. Thêm một cuộc gọi hệ thống mới trong hạt nhân Linux 3.3
- 12. Bảng gọi hệ thống trong hạt nhân Linux ở đâu?
- 13. Hạt nhân CUDA có thể gọi hàm cublas không?
- 14. Viết nhiều hạt nhân hoặc một hạt nhân
- 15. Linux mutexes hạt nhân
- 16. làm thế nào để chương trình giao tiếp - hạt nhân vi hạt nhân nguyên khối hạt nhân exo
- 17. Tại sao Python không gọi phương thức instance __init __() khi tạo cá thể nhưng các lớp gọi __init __() thay thế?
- 18. Xác định địa chỉ tải và điểm vào của hình ảnh hạt nhân Linux bị tước
- 19. Tải mô-đun hạt nhân trong hạt nhân Android
- 20. Xác định mô-đun hạt nhân đã tạo mục nhập sysfs
- 21. Đối số hạt nhân
- 22. Người gọi chức năng trong hạt nhân Linux
- 23. Cách đọc/ghi tệp trong mô-đun hạt nhân Linux?
- 24. Libsvm precomputed hạt nhân
- 25. Gọi hàm xác định jQuery qua chuỗi
- 26. Khả năng tương thích của hạt nhân Linux (* .ko) giữa các hạt nhân
- 27. Android: Cách nhận nhật ký hạt nhân sau khi hoảng loạn hạt nhân?
- 28. Python: nhiều cuộc gọi đến __init __() trên cùng một ví dụ
- 29. cuộc gọi đến không xác định chức năng exif_read_data()
- 30. C# 4: Xác định tham số truyền ngữ nghĩa trong các cuộc gọi động