Fork () neden bir dosya tanımlayıcı döndürecek şekilde tasarlanmalıdır?


16

Onun üzerinde yaklaşık web sayfasında kendini boru hile Dan Bernstein bir yarış ile durumu açıklar select()ve sinyalleri, teklifler geçici bir çözüm ve sonucuna varır

Elbette, Doğru Şey fork(), bir işlem tanıtıcısı değil, bir dosya tanıtıcısı döndürmek olacaktır .

Bununla ne anlama geliyor - select()bu durum değişikliklerinden haberdar olmak için bir sinyal işleyici kullanmak yerine, çocuk süreçlerinde durum değişikliklerini idare edebilmekle ilgili bir şey mi?


Bu makale girdi ve çıktıyı karıştırıyor mu yoksa doğru okumuyor muyum?
ctrl-alt-delor

Borular üzerinden sinyal gönderilmesini isteyebilirsiniz. Yaptığım budur.
ctrl-alt-delor

@ ctrl-alt-delor. Bu metin 2003'ten geldi ve emin değilim signalfdve o zamanlar böyle bir şey vardı?
ilkkachu

5
Dan kasten kışkırtıcı olabilmesine rağmen, neden bahsettiğini biliyor. Kasten kışkırtıcı olsaydım, tabii ki, Doğru Şey SIGCHLD'den kurtulmak olurdu.
Steve Summit

1
@mosvy Biraz abartıyorum, ama SIGCHLD'u kullanmaya çalışan her programın ve gördüğüm her programlayıcının sorunları vardı. Bu gerçekleşmeyi bekleyen bir yarış koşulu. Tüm sahip olduğumuz engelleme olduğunda wait(), yapamayacağınız şeyler vardı, bu yüzden birisi SIGCHLD'u icat etti, ama kötü bir işti. Tecrübelerime göre, şimdi de var olduğunu, tıkanmasızdır, güzel bir yağmurlama wait3(), wait4()ve / veya waitpid()anahtar yerlerde aramalar (belki ana olay döngü) çok üstün bir alternatiftir.
Steve Summit

Yanıtlar:


14

Sorun kaynağınızda açıklanıyor, select()gibi sinyaller tarafından kesilmeli SIGCHLD, ancak bazı durumlarda iyi çalışmıyor. Bu nedenle geçici çözüm, daha sonra izlenen bir boruya sinyal yazmadır select(). Dosya tanımlayıcıları izlemek select()bunun için bir şeydir , bu yüzden sorun etrafında çalışır.

Geçici çözüm, esasen signal olayını bir dosya tanımlayıcı olayına dönüştürür. Eğer fork()sadece ilk etapta bir fd döndüğünü fd sonra muhtemelen doğrudan kullanılabilecek şekilde, geçici çözüm, gerekli olmaz select().

Evet, son paragraftaki açıklamanız bana doğru görünüyor.


Bir fd'nin (veya başka bir tür çekirdek tanıtıcısının) düz bir işlem kimlik numarasından daha iyi olmasının bir başka nedeni de, işlem bittikten sonra PID'lerin yeniden kullanılabilmesidir. Bu, bazı durumlarda süreçlere sinyal gönderirken bir sorun olabilir, sürecin düşündüğünüzden emin olmak mümkün olmayabilir ve aynı PID'yi tekrar kullanan bir başkası değil. (Bununla birlikte, bir çocuk sürecine sinyal gönderirken bunun bir sorun olmaması gerektiğini düşünüyorum, çünkü ebeveyn wait()PID'nin serbest bırakılması için çocuğu çalıştırmalıdır .)


Bununla birlikte, PID ile ilgili olarak okuduğum vakaların tam olarak bir sorun olduğunu hatırlamıyorum, bu yüzden herhangi biri bunu ayrıntılı olarak açıklamak veya açıklığa kavuşturmak, hatta yukarıdakileri düzenlemek istiyorsa, bunu yapmaktan çekinmeyin.
ilkkachu

2
Daha önce de belirttiğiniz gibi, bir ebeveynin kendi çocuk pid'inin yeniden kullanıldığını bulması için hiçbir mazeret yoktur. Bu durum tam olarak kontrol altındadır, çünkü arayan odur wait().
Joshua

Bunlara zombi süreçleri denir : "yürütme işlemini tamamlamış ancak işlem tablosunda hala bir giriş var:" Sonlandırılmış durum "daki bir işlemdir. çıkış durumunu okuma süreci "
Lassi

6
Şimdi Linux söz It değerinde olabilir bir dosya tanıtıcı (pidfd) return clonefiili sistem çağrısı LInux üzerinde olduğu çatal çağırır olduğunu. Bunu etkinleştirmek için işaret denir CLONE_PIDFD- Bkz. Örneğin lwn.net/Articles/784831 .
KJ Tsanaktsidis

1
@Lie Ryan, Re " fork () yerel bir tanıtıcı yerine genel bir tanıtıcı döndürür kavramsal olarak daha doğru çünkü ", Windows işlem tanıtıcıları kullanır. Pid ve çıkış kodu, işlemin tüm tutamaçları kapanana kadar (ebeveynin toplanmasını beklemek yerine), unix sistemlerinde yaygın olan yarış koşullarından kaçınarak etrafta dolaşır. Kulplar süreci canlı tuttuğunda, küresel kulplardan ziyade yerel kulp olmaları çok daha mantıklıdır.
ikegami

9

Bu sadece "Unix'in olduğundan farklı bir şekilde tasarlanması harika olurdu" satırında bir musing.

PID'lerle ilgili sorun, başka bir işlem için yeniden kullanılabilecekleri küresel bir ad alanında yaşadıkları fork()ve ebeveyne her zaman alt sürece başvurması garanti edilecek bir tür tanıtıcı döndürülmesi iyi olurdu ve kalıtım veya unix soketleri ile diğer işlemlere geçebilir / SCM_RIGHTS[1].

Ayrıca tartışma bakın burada bir bayrak ekleme dahil Linux, içinde o "düzeltme" için son bir çaba için clone()hangi bir pid-fd yerine PID dönmesine neden olur.

Ancak o zaman bile, bu kendi kendine boru korsanlığı [2] veya daha iyi arayüzlere olan ihtiyacı ortadan kaldırmaz, çünkü bir çocuğun durumu hakkında bir ana süreci bildiren sinyaller ana döngüde ele almak istediğiniz tek şey değildir. programın. Ne yazık ki, epoll(7) + signalfd(2)Linux veya kqueue(2)BSD gibi şeyler standart değildir - tek standart arayüz (ancak eski sistemlerde desteklenmez) çok daha düşüktür pselect(2).

[1] waitpid()Sistem çağrısının geri döndüğü ve dönüş değerinin kullanıldığı zamana kadar PID'nin geri çevrilmesini önleme, muhtemelen waitid(.., WNOWAIT)bunun yerine yeni sistemlerde elde edilebilir .

[2] DJ Bernstein'ın onu icat ettiğini iddia etmesi üzerine yorum yapmazdım (apophasis için özür dilerim ;-)).


8

Bernstein bu "Doğru Şey" sözüne pek fazla bağlam vermez, ama bir tahminde bulunacağım: Çatalı (2) döndürmek bir PID'ye sahip olmak, açık (2), creat (2) vb. Döndüren dosya tanımlayıcılarıyla tutarsız. Unix sisteminin geri kalanı, bir PID yerine bir işlemi temsil eden bir dosya tanımlayıcı ile işlem manipülasyonu yapmış olabilir. Sinyaller ve dosya tanımlayıcıları arasında biraz daha iyi etkileşime izin veren ve bir işlemi temsil eden dosya tanımlayıcısının çalışabileceğini gösteren bir sistem çağrısı signalfd (2) vardır.


signalfd (2) harika görünüyor, bahsettiğiniz için teşekkürler! Çok kötü, sadece Linux için.
Lassi

1
pidfd_openLinux'ta da tartışmalar oldu , bkz. Lwn.net/Articles/789023
dhag
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.