hangi dosya tanımlayıcılarının aynı “açık dosya tanımını” paylaştığını öğrenin


17

Eğer yaparsam (Bourne benzeri bir kabukta):

exec 3> file 4>&3 5> file 6>> file

Dosya tanımlayıcıları 3 ve 4, 4 dup()3'ten edindiğinden, aynı açık dosya açıklamasını paylaşın (aynı özellikler, dosya içindeki aynı ofset ...). Bu işlemin dosya tanımlayıcıları 5 ve 6 farklı bir açık dosya tanımındayken (örneğin, her biri dosyada kendi işaretçilerine sahiptir).

Şimdi, lsofçıktı olarak, tek gördüğümüz:

zsh     21519 stephane    3w   REG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    4w   REG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    5w   REG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    6w   REG  254,2        0 10505865 /home/stephane/file

Şununla biraz daha iyi lsof +fg:

zsh     21519 stephane    3w   REG          W,LG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    4w   REG          W,LG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    5w   REG          W,LG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    6w   REG       W,AP,LG  254,2        0 10505865 /home/stephane/file

(burada Linux 3.16'da) fd 6'nın farklı bayrakları olduğunu görüyoruz, bu yüzden fd 3, 4 veya 5'tekinden farklı bir açık dosya açıklaması olmalı , ancak bundan fd 5'in farklı açık dosya açıklaması . İle -o, ofseti de görebiliyoruz, ancak yine aynı ofset, aynı açık dosya açıklaması olduğunu garanti etmiyor .

Bunu bulmanın müdahaleci olmayan 1 yolu var mı? Harici olarak mı, yoksa bir işlemin kendi dosya tanımlayıcıları için mi?


1 . Sezgisel bir yaklaşım, bir fd'nin bayraklarını değiştirmek ve fcntl()sonuç olarak diğer dosya tanımlayıcılarının bayraklarını güncellediğini görmek olabilir, ancak bu ideal veya aptal kanıt değildir.


Bu yaklaşım prensipte işe yaramalı ve çoğu senaryoda çok yıkıcı olmamalıdır: ilk önce bir çocuğu çatallayın (dışarıdan yapıyorsa çok fazla). Ardından, alt dosyada, dosya tanımlayıcıyla diğer işlemleri etkilemeyen bir şey yapın. Linux'ta kiralamalar bunun için çalışmalıdır.
Gilles 'SO- kötü olmayı kes

@Gilles, teşekkürler ama bu zaten soruda önerdiğim yaklaşım. kiralamalar (F_SETLEASE fcntl demek istediğinizi varsayarsak, onları BTW'den haberdar ettiğiniz için teşekkürler) aynı dosyaya (EBUSY) başka bir "yazma" açık dosya açıklaması varsa değil , yalnızca sahip olduğunuz normal dosyalar için çalışır ve tam olarak olmayan -intrusive.
Stéphane Chazelas

Bu soruyu terk ettin mi? SystemTap'in istediğinizi nasıl yapabileceği hakkında bazı bilgiler yayınladım, ancak herhangi bir cevabı tam olarak işaretlemediniz ...
Azhrei

Yanıtlar:


2

Linux 3.5 ve sonrası için bu kcmp (3) ile gerçekleştirilebilir :

KCMP_FILE

  • Bir dosya tanıtıcı olup olmadığını kontrol edin idx1 süreci PID1 aynı açık dosya tarifine atıfta bulunur (bkz açık (2) olarak dosya tanıtıcısı) idx2 süreci PID2 . Aynı açık dosya tanımına başvuran iki dosya tanımlayıcısının varlığı, dup (2) (ve benzeri) fork (2) veya bir dosya soketinden dosya tanımlayıcıları geçirmenin bir sonucu olarak ortaya çıkabilir (bkz. Unix (7) ).

Man sayfası OP'nin istediği kullanım örneği için özel bir örnek sunar. Bu sistem çağrısının çekirdeğin kümeyle derlenmesini gerektirdiğini unutmayın CONFIG_CHECKPOINT_RESTORE.


Teşekkürler. Tam olarak aradığım şey. Süper kullanıcı değilseniz, iki işleminizin olması gerektiğini (ve setuid / setgid ...) (anlaşılır bir şekilde) olması gerektiğini unutmayın
Stéphane Chazelas

@ StéphaneChazelas Kesinlikle. Herhangi bir nedenden dolayı CPIU desteği çekirdeğinizde oluşturulmamışsa ve yeniden oluşturmak istemiyorsanız, her zaman struct file *işaretçileri karşılaştırmanıza izin veren bazı kullanıcı arabirimi dışa aktaran bir çekirdek modülü yazabileceğinizi varsayalım .
minmaxavg

3

Karşılaştırmak struct fileistediğiniz, dosya tanımlayıcılarının işaret ettiği işaretçilerdir. (İçinde çekirdeği biridir task_structO adlı başka yapıya bir işaretçi içerir. Her iş parçacığı için veri yapısı files_struct. Ve bu yapı işaretçiler bir dizi, bir her birini içeriyorsa struct file. O var struct fileofset aramaya açık bayrakları ve a tutan diğer birkaç alan.)

İşaretçileri files_structdiğer müdahaleci araçların kullanımı dışında görmek için kullanıcı tarafından görülebilir bir yol bilmiyorum . Örneğin, SystemTap'e bir PID verilebilir ve karşılık geleni bulabilir task_structve işaretçileri izleyebilir. Eğer pasif arıyorsanız, bunun hakkında olduğunu düşünüyorum. Dell, uzun süre önce canlı çekirdek belleğine elektronik tablo benzeri bir arabirim veren KME (Çekirdek Bellek Düzenleyicisi) adlı bir araç yayınladı ve istediğinizi yapabildi, ancak 64 bit'e hiç taşınmadı. (Denedim ve hiçbir zaman tamamen işe yaramadı ve neden olduğundan emin değildi.)

lsofYararlı olmamanızın bir nedeni de bu işaretçileri görmemesidir (ancak +fLinux olmayan sistemler seçeneğine bakın). Teorik olarak içindeki tüm alanları karşılaştırabilir struct fileve iki yapının aynı olduğunu düşünebilirsiniz, ancak yine de ayrı open(2)çağrılardan olabilirler.

Fikirler için pfiles SystemTap betiğine bir göz atın . Adresini yazdıracak şekilde değiştirirseniz struct file, çözümünüz olur. Ayrıca , üzerinde yürüyen bir işlev olduğu için, open_file_by_pid.stp dosyasını da kontrol edebilirsinizfiles_struct . dosya tanımlayıcı tablosu, struct filenesnelere bakarak ...

Neyi başarmaya çalıştığınızı sorabilir miyim?


İtiraf etmeliyim ki ihtiyaç duyduğum davayı hatırlayamıyorum. Şüphesiz bazı hata ayıklama veya adli görevler.
Stéphane Chazelas

PoC systemtap kodunu dört gözle bekliyorum :-)
Stéphane Chazelas 14:15

Soruyu göndermeden önce, systemtap veya / proc / kcore yaklaşımlarına bir göz attım. Zor olan kısım, her görevin her bir parçası için bilgi almaktı . Bulduğum en umut verici yaklaşım, / proc / * / task / fd dizininin içeriğini oluşturan işlevlere bağlanmaktı, ancak kaynak dosyadaki belirli satır numaralarına takılmaya çalışabildiğim tek uygulanabilir şey bir çekirdek sürümünden diğerine taşınabilir. Systemtap'taki görev listesinde gerçek anlamda geçiş yapamazsınız. Belki / proc / kcore ile mümkün, ama çok fazla çaba ve muhtemelen güvenilmez.
Stéphane Chazelas

Şimdiye kadarki en iyi yanıt için teşekkürler. Göstergelerinize bir göz atacağım.
Stéphane Chazelas

Tabi ki yapabilirsin! Bir probe beginblok oluşturun ve for_each_processmakroyu komut dosyasına gömülü bir C kodu bloğunda kullanmasını sağlayın (C kodunu gömmek için "guru" modu SystemTap kullanmanız gerekir). Aslında, bunu ilginç kılmak (!) İçin SystemTap'in ilişkilendirilebilir dizilerinden birini kullanabilirsiniz; kullanmak files_structanahtar olarak adres ve değerler olarak PID'ler / Tıd'ler bir listesini. Artık açılan her dosyanın ve bunları paylaşan görevlerin bir listesine sahipsiniz (bunlar üst öğe / alt öğe arasında paylaşılabilir). SystemTap'i tartışmak isterseniz tekrar yanıtlayın.
Azhrei

0

İşte linux'a özgü bir çözüm: / proc / self / fd, geçerli işlemdeki açık dosya tanıtıcıları için sembolik bağlantıların bir dizinidir. Sadece bağlantı değerlerini karşılaştırabilirsiniz. Bir çocuk süreci kullanılırken daha karmaşık hale gelir, çünkü çocuğa farklı / proc / benlik olacaktır çünkü pid bağımlı bir sembolik bağlantıdır. / Proc / $$ / fd komutunu kullanarak bu sorunu geçici olarak çözebilirsiniz; burada $$ istenen pid'dir.


Teşekkürler. Ama sorduğum bu değil. Linux'ta, lsof her dosya tanımlayıcı için yolları almak için / proc / pid / fd ve bayraklar için / proc / pid / fdinfo kullanır. Ama istediğim, ister aynı açık dosya tanımına işaret olsun ister iki dosya tanımlayıcıları bağımsız olarak açık olsun, aynı dosyaya iki fds için .
Stéphane Chazelas

tamam, aynı dosya adına açık olan dosya tanımlayıcı çiftlerini bulduktan sonra, her ikisinde de bir açıklama yapın ve sonuçları karşılaştırın, eğer farklıysalar ayrıdırlar. Bir dosya tanımlayıcısında aynı arayış ve tekrarlarsa, yine de eşleşiyorlarsa aynıdırlar.
hildred

Bu, soruda bahsettiğim sezgisel yaklaşımın daha müdahaleci bir varyantıdır ve bu sadece normal dosyalar için çalışır (soketler, cihazlar (terminaller gibi), borular ...).
Stéphane Chazelas
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.