Çekirdekteki hangi dosya sys_clone () sistem çağrısını kullanmak için fork (), vfork ()… belirtir


9

Sistem çağrılarını izlemek için ltrace kullanıldığında fork () 'un sys_fork () yerine sys_clone () kullandığını görebiliyordum. Ama linux kaynağını tanımlandığı yerde bulamadım.

Benim programım

#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");

}

Ve ltrace çıktısı

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) +++

Bu sizin için yararlı olabilir: lxr.linux.no/linux+v3.10.9
tekrar oynat

@ mauro.stettler Ben lxr bulamadım
user3539

Şunu mu demek istediniz: git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/… line 1700 Ne bulmayı umuyordun?
msw

Yanıtlar:


29

Glibc içindeki fork()ve vfork()sarmalayıcıları clone()sistem çağrısı yoluyla uygulanır . Daha iyi arasındaki ilişkiyi anlamak için fork()ve clone()biz Linux süreçler ve iş parçacıkları arasındaki ilişkiyi göz önüne almalıyız.

Geleneksel olarak, fork()üst sürecin sahip olduğu tüm kaynakları yayımlar ve kopyayı alt sürece atar. Bu yaklaşım, çocuk derhal ararsa, hiçbir şey için olmayabilir exec(). Linux'ta, üst ve alt işlemler arasında paylaşılabilecek verilerin kopyalanmasını geciktirmek veya tamamen önlemek için yazma üzerine kopyalama sayfalarını fork()kullanır . Bu nedenle, normal sırasında gerçekleşen tek ek yük , ebeveynin sayfa tablolarının kopyalanması ve çocuk için benzersiz bir süreç tanımlayıcı yapısının atanmasıdır .fork()task_struct

Linux ayrıca iş parçacıklarına olağanüstü bir yaklaşım getiriyor. Linux'ta, iş parçacıkları bazı kaynakları diğer işlemlerle paylaşan sıradan süreçlerdir. Bu, işlemlerin ve iş parçacıklarının tamamen farklı hayvan türleri olduğu Windows veya Solaris gibi diğer işletim sistemlerine kıyasla iş parçacıklarına kökten farklı bir yaklaşımdır. Linux'ta, her iş parçacığının, task_structadres alanı gibi belirli kaynakları üst süreçle paylaşacak şekilde ayarlanması gereken bir sıradan vardır .

flagsParametre clone()sistemi çağrısı varsa üst ve alt süreçler paylaşmalıdır, hangi kaynakları gösteren bir bayrak kümesi içerir. İşlemler ve iş parçacıkları yoluyla oluşturulur clone(), tek fark geçirilen bayrak kümesidir clone().

Bir normal fork()şu şekilde uygulanabilir:

clone(SIGCHLD, 0);

Bu, üst kaynağı ile herhangi bir kaynak paylaşmayan bir görev oluşturur ve SIGCHLDsonlandırıldığındaki sonlandırma sinyalini üst öğeye gönderecek şekilde ayarlanır .

Buna karşılık, adres alanını, dosya sistemi kaynaklarını, dosya tanımlayıcılarını ve sinyal işleyicilerini üst öğeyle, başka bir deyişle bir iş parçacığıyla paylaşan bir görev şu şekilde oluşturulabilir:

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

vfork()sırayla, CLONE_VFORKalt süreç bir sinyal ile uyanana kadar ana sürecin uyumasına neden olacak ayrı bir bayrakla uygulanır . Çocuk, çağrılıncaya exec()veya çıkana kadar ebeveynin ad alanındaki tek yürütme dizisi olacaktır . Çocuğun belleğe yazmasına izin verilmiyor. İlgili clone()çağrı aşağıdaki gibi olabilir:

clone(CLONE_VFORK | CLONE_VM | SIGCHLD, 0)

Uygulanması sys_clone()mimariye özgüdür, ancak çalışmanın büyük bölümü do_fork()tanımlandığı yerdedir kernel/fork.c. Bu işlev clone_process(), üst öğenin bir kopyası olarak yeni bir işlem oluşturan ancak henüz başlatılmayan statiki çağırır . clone_process()kayıtları kopyalar, yeni göreve bir PID atar ve klon tarafından belirtildiği gibi işlem ortamının uygun kısımlarını yayımlar veya paylaşır flags. Ne zaman clone_process()döner, do_clone()yeni oluşturulan süreç uyandırmak ve zamanlayacak çalışmasına.


2
+1 clone()Diş ve çatallara göre öneminin güzel açıklaması .
goldilocks

1
Tüm şüphelerim temizlendi
user3539

2

Kullanıcı sistemi çağrı işlevlerini Linux altında çekirdek sistem çağrılarına çevirmekten sorumlu bileşen libc'dir. GLibC'de, NPTL kütüphanesi bunu clone(2)sistem çağrısına yönlendirir .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.