2.6 Kernel Linux'ta Çatal vs Klon


37

Çatal ve klonla ilgili kafam karıştı. Bunu görmüştüm:

  • çatal süreçler için ve klon dişler için

  • çatal sadece klon çağırır, klon tüm işlemler ve konular için kullanılır

Bunlardan herhangi biri doğru mu? 2.6 Linux çekirdeğine sahip bu iki sistem arasındaki fark nedir?

Yanıtlar:


52

fork()Orijinal UNIX sistem çağrısıydı. İş parçacığı değil, yalnızca yeni işlemler oluşturmak için kullanılabilir. Ayrıca, taşınabilir.

Linux'ta, clone()yeni bir yürütme iş parçacığı oluşturmak için kullanılabilecek yeni, çok yönlü bir sistem çağrısıdır. Geçilen seçeneklere bağlı olarak, yeni yürütme iş parçacığı bir UNIX işleminin, bir POSIX iş parçacığının, aralarındaki bir şeyin ya da tamamen farklı bir şeyin (farklı bir kap gibi) anlamına uygun olabilir. Belleğin, dosya tanımlayıcıların, çeşitli ad alanlarının, sinyal işleyicilerinin vb. Paylaşılıp paylaşılmamasını belirleyen her türlü seçeneği belirleyebilirsiniz.

Yana clone()üst küme sistem çağrısı, uygulanmasıdır fork()glibc aslında çağrılarda sistem çağrı sarıcı clone(), ancak bu programcılar hakkında bilmek gerekmez bir uygulama ayrıntıdır. Asıl gerçek fork()sistem çağrısı, Linux çekirdeğinde, gereksiz olmasına rağmen geriye dönük uyumluluk nedenlerinden dolayı hala mevcuttur, çünkü libcc'nin çok eski sürümlerini veya glibc'nin yanı sıra başka bir libc'i kullanan programlar da kullanabilir.

clone()ayrıca pthread_create()iş parçacığı oluşturmak için POSIX işlevini uygulamak için kullanılır .

Taşınabilir programlar çağırmalıdır fork()ve pthread_create()değil clone().


2
posix_spawn başka bir önemli fonksiyondur - hem çataldan hem de portatifden daha az taşınabilir.
Random832

10

clone()Linux 2.6'da iki şey varmış gibi görünüyor.

Bir sistem çağrısı var:

int clone(int (*fn)(void *), void *child_stack,
          int flags, void *arg, ...
          /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );

Bu yaparak açıklanan "klon ()" dir man 2 clone.

Bu adam sayfasını yeterince okursanız, şunu göreceksiniz:

It is actually a library function layered on top of the
underlying clone() system call.

Görünüşe göre, kafa karıştırıcı olarak aynı adlandırılmış sistem çağrısında bulunan "kütüphane işlevini" kullanarak iş parçacığı uygulamanız gerekiyor.

Kısa bir program yazdım:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int
main(int ac, char **av)
{
    pid_t cpid;
    switch (cpid = fork()) {
    case 0:   // Child process
        break;
    case -1:  // Error
        break;
    default:  // parent process
        break;
    }
    return 0;
}

İle derleyin:, c99 -Wall -Wextrave strace -fforking ne diyor aslında görmek için sistem koştu . Bunu straceLinux 2.6.18 makinesinde (x86_64 CPU) çıkardım :

20097 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x2b4ee9213770) = 20098
20097 exit_group(0)                     = ?
20098 exit_group(0)

straceÇıkışta "çatal" çağrısı görünmez . clone()İçinde gösterir yukarı o çağrı straceçıkışı adam sayfalık-klon çok farklı argümanlar vardır. child_stack=0ilk argüman farklı olduğundan int (*fn)(void *).

fork(2)Sistem çağrısının tıpkı "kütüphane işlevi" nin uygulandığı gibi gerçek anlamda yapıldığı anlaşılmaktadır . Gerçek insan sayfa-klon gelen argümanlar farklı bir dizi vardır.clone()clone() clone()

Basitçe, hem görünüşte çelişkili ifadeleriniz hakkında fork()hem clone()de doğru. Bununla birlikte, söz konusu "klon" farklıdır.


9
“Bu aslında, alttaki clone () sistem çağrısının üstüne yerleştirilmiş bir kütüphane işlevidir.” - Genel olarak, bu her sistem çağrısı için geçerlidir. Programcılar aslında hemen hemen her zaman sistem çağrısından sonra adlandırılmış olan libc'deki fonksiyonları çağırırlar. Bunun nedeni, doğrudan C'den gerçek bir sistem çağrısı yapmak, platforma özgü sihir (genellikle bir tür CPU tuzağını zorlayarak, ABI mimarisine bağlıdır) ve libc'ye bırakılmış en iyi makine kodunu gerektirir.
Celada

1
@Celada - evet, kabul etti. Sadece man 2 clonetam olarak bu şekilde ifade ediyor, konunun kafasını karıştırdığını ve sorgulayıcının iyi bir cevap almasını engellediğini düşünüyorum.
Bruce Ediger,

2
Ben manpage araçları belirtmek için inanıyoruz argüman listesi ait clonetemeldeki sistem çağrısıyla kabul edilen görüşe göre listeden ölçüde kütüphane işlevi farklıdır. Spesifik olarak, sistem çağrısı her zaman aynı şekilde iki kez geri döner, geleneksel yöntemle fork; alt yığına ilişkin tüm argümanlar kesinlikle kullanıcı alanında ele alınır. Örneğin bakınız sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/...
Zwol

1
Cevabınızı en iyi cevabı vermek istedim çünkü çok güzel, ama sürü tarafından sallandım ve ilk cevabı buldum. Tepki süresi için puan alıyor. Açıklaman için teşekkürler.
Gregg Leventhal

6

fork()sistem çağrısına sadece belirli bir bayrak kümesidir clone(). clone()Bir "işlem" veya "iş parçacığı" ya da işlemler ve iş parçacıkları arasında (örneğin, aynı dosya tanımlayıcı tablosunu paylaşan farklı "işlemler") bir yerde tuhaf şeyler yaratacak kadar geneldir.

Temel olarak, çekirdekte bir yürütme bağlamıyla ilişkili her "bilgi" türü için, clone()size bu bilgiyi takma ya da kopyalama tercihini verir. Konular takma adlara karşılık gelir, işlemler kopyalamaya karşılık gelir. Bayrakların ara kombinasyonlarını belirleyerek clone(), iş parçacığı veya işlem olmayan garip şeyler oluşturabilirsiniz. Genelde bunu yapmamalısınız ve Linux çekirdeğinin gelişimi sırasında böyle bir genel mekanizmaya izin verip vermeyeceği konusunda bazı tartışmalar olduğunu hayal ediyorum clone().

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.