Tập tin nào trong kernel chỉ định fork (), vfork () 'để sử dụng lệnh gọi hệ thống sys_clone ()


9

Khi ltrace được sử dụng để theo dõi các cuộc gọi hệ thống, tôi có thể thấy fork () sử dụng sys_clone () thay vì sys_fork (). Nhưng tôi không thể tìm thấy nguồn linux nơi nó được định nghĩa.

Chương trình của tôi là

#include<stdio.h>
main()
{
        int pid,i=0,j=0;
        pid=fork();
        if(pid==0)
                printf("\nI am child\n");
        else
                printf("\nI am parent\n");

}

Và sản lượng ltrace là

SYS_brk(NULL)                                                                               = 0x019d0000
SYS_access("/etc/ld.so.nohwcap", 00)                                                        = -2
SYS_mmap(0, 8192, 3, 34, 0xffffffff)                                                        = 0x7fe3cf84f000
SYS_access("/etc/ld.so.preload", 04)                                                        = -2
SYS_open("/etc/ld.so.cache", 0, 01)                                                         = 3
SYS_fstat(3, 0x7fff47007890)                                                                = 0
SYS_mmap(0, 103967, 1, 2, 3)                                                                = 0x7fe3cf835000
SYS_close(3)                                                                                = 0
SYS_access("/etc/ld.so.nohwcap", 00)                                                        = -2
SYS_open("/lib/x86_64-linux-gnu/libc.so.6", 0, 00)                                          = 3
SYS_read(3, "\177ELF\002\001\001", 832)                                                     = 832
SYS_fstat(3, 0x7fff470078e0)                                                                = 0
SYS_mmap(0, 0x389858, 5, 2050, 3)                                                           = 0x7fe3cf2a8000
SYS_mprotect(0x7fe3cf428000, 2097152, 0)                                                    = 0
SYS_mmap(0x7fe3cf628000, 20480, 3, 2066, 3)                                                 = 0x7fe3cf628000
SYS_mmap(0x7fe3cf62d000, 18520, 3, 50, 0xffffffff)                                          = 0x7fe3cf62d000
SYS_close(3)                                                                                = 0
SYS_mmap(0, 4096, 3, 34, 0xffffffff)                                                        = 0x7fe3cf834000
SYS_mmap(0, 4096, 3, 34, 0xffffffff)                                                        = 0x7fe3cf833000
SYS_mmap(0, 4096, 3, 34, 0xffffffff)                                                        = 0x7fe3cf832000
SYS_arch_prctl(4098, 0x7fe3cf833700, 0x7fe3cf832000, 34, 0xffffffff)                        = 0
SYS_mprotect(0x7fe3cf628000, 16384, 1)                                                      = 0
SYS_mprotect(0x7fe3cf851000, 4096, 1)                                                       = 0
SYS_munmap(0x7fe3cf835000, 103967)                                                          = 0
__libc_start_main(0x40054c, 1, 0x7fff47008298, 0x4005a0, 0x400590 <unfinished ...>
fork( <unfinished ...>
SYS_clone(0x1200011, 0, 0, 0x7fe3cf8339d0, 0)                                               = 5967
<... fork resumed> )                                                                        = 5967
puts("\nI am parent" <unfinished ...>
SYS_fstat(1, 0x7fff47008060)                                                                = 0
SYS_mmap(0, 4096, 3, 34, 0xffffffff
)                                                        = 0x7fe3cf84e000
I am child
SYS_write(1, "\n", 1
)                                                                       = 1
SYS_write(1, "I am parent\n", 12)                                                           = -512
--- SIGCHLD (Child exited) ---
SYS_write(1, "I am parent\n", 12I am parent
)                                                           = 12
<... puts resumed> )                                                                        = 13
SYS_exit_group(13 <no return ...>
+++ exited (status 13) +++

Điều này có thể hữu ích cho bạn: lxr.linux.no/linux+v3.10.9
phát lại

@ mauro.stettler Tôi không thể tìm thấy nó trong lxr
user3539

Ý của bạn là git.kernel.org/cgit/linux/kernel/git/urdy/linux-urdy.git/ trên khoảng 1700? Bạn đã hy vọng tìm ra điều gì?
msw

Câu trả lời:


29

Các hàm fork()vfork()hàm trong glibc được thực hiện thông qua lệnh clone()gọi hệ thống. Để hiểu rõ hơn về mối quan hệ giữa fork()clone(), chúng ta phải xem xét mối quan hệ giữa các tiến trình và luồng trong Linux.

Theo truyền thống, fork()sẽ công khai tất cả các tài nguyên thuộc sở hữu của quy trình cha mẹ và gán bản sao cho quy trình con. Cách tiếp cận này phát sinh chi phí đáng kể, tất cả có thể chẳng là gì nếu đứa trẻ gọi ngay lập tức exec(). Trong Linux, fork()sử dụng các trang sao chép khi ghi để trì hoãn hoặc hoàn toàn tránh sao chép dữ liệu có thể được chia sẻ giữa các tiến trình cha và con. Do đó, chi phí duy nhất phát sinh trong quá trình bình thường fork()là sao chép bảng trang của cha mẹ và gán cấu trúc mô tả quy trình duy nhất task_struct, cho trẻ.

Linux cũng có một cách tiếp cận đặc biệt đối với các chủ đề. Trong Linux, các luồng chỉ là các quy trình thông thường xảy ra để chia sẻ một số tài nguyên với các quy trình khác. Đây là một cách tiếp cận hoàn toàn khác nhau đối với các luồng so với các hệ điều hành khác như Windows hoặc Solaris, nơi các quy trình và luồng là các loại quái thú hoàn toàn khác nhau. Trong Linux, mỗi luồng có một thông thường task_structriêng của nó, tình cờ được thiết lập theo cách nó chia sẻ một số tài nguyên nhất định, chẳng hạn như một không gian địa chỉ, với quy trình cha.

Các flagstham số của các clone()cuộc gọi hệ thống bao gồm một bộ cờ mà chỉ ra nguồn lực, nếu có, các quá trình cha mẹ và con nên chia sẻ. Các quy trình và luồng đều được tạo thông qua clone(), sự khác biệt duy nhất là tập hợp các cờ được truyền tới clone().

Một bình thường fork()có thể được thực hiện như:

clone(SIGCHLD, 0);

Điều này tạo ra một tác vụ không chia sẻ bất kỳ tài nguyên nào với cha mẹ của nó và được đặt để gửi SIGCHLDtín hiệu kết thúc cho cha mẹ khi nó thoát.

Ngược lại, một tác vụ chia sẻ không gian địa chỉ, tài nguyên hệ thống tệp, mô tả tệp và trình xử lý tín hiệu với cha mẹ, nói cách khác, một luồng , có thể được tạo bằng:

clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, 0);

vfork()lần lượt được thực hiện thông qua một CLONE_VFORKcờ riêng biệt , điều này sẽ khiến tiến trình cha mẹ ngủ cho đến khi tiến trình con đánh thức nó qua tín hiệu. Đứa trẻ sẽ là luồng xử lý duy nhất trong không gian tên của cha mẹ, cho đến khi nó gọi exec()hoặc thoát. Đứa trẻ không được phép ghi vào bộ nhớ. Cuộc clone()gọi tương ứng có thể như sau:

clone(CLONE_VFORK | CLONE_VM | SIGCHLD, 0)

Việc thực hiện sys_clone()là kiến ​​trúc cụ thể, nhưng phần lớn công việc xảy ra trong do_fork()định nghĩa trong kernel/fork.c. Hàm này gọi tĩnh clone_process(), tạo ra một quy trình mới dưới dạng bản sao của cha mẹ, nhưng chưa khởi động nó. clone_process()sao chép các thanh ghi, gán một PID cho tác vụ mới và cấp phép hoặc chia sẻ các phần thích hợp của môi trường quy trình theo quy định của bản sao flags. Khi clone_process()trở về, do_clone()sẽ đánh thức quá trình vừa tạo và lên lịch để chạy.


2
+1 Giải thích hay về tầm quan trọng của clone()mối quan hệ với chủ đề và dĩa.
goldilocks

1
Xóa tất cả nghi ngờ của tôi
dùng3539

2

Thành phần chịu trách nhiệm dịch các hàm gọi hệ thống người dùng sang các cuộc gọi hệ thống kernel trong Linux là libc. Trong GLibC, thư viện NPTL chuyển hướng điều này đến clone(2)cuộc gọi hệ thống.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.