लिनक्स वास्तविक और गैर-मौजूदा (जैसे: डिवाइस) फ़ाइलों के बीच अंतर कैसे करता है?


28

यह एक निम्न स्तर का प्रश्न है, और मैं समझता हूं कि यह पूछने के लिए सबसे अच्छी जगह नहीं हो सकती है। लेकिन, यह किसी भी अन्य एसई साइट की तुलना में अधिक उपयुक्त लग रहा था, इसलिए यहां जाता है।

मुझे पता है कि लिनक्स फाइल सिस्टम पर, कुछ फाइलें वास्तव में मौजूद हैं , उदाहरण के लिए: /usr/bin/bashवह मौजूद है। हालांकि, (जहाँ तक मैं यह समझ के रूप में), कुछ भी वास्तव में इस तरह के रूप में मौजूद नहीं है और कर रहे हैं और अधिक आभासी फ़ाइलें, जैसे: /dev/sda, /proc/cpuinfo, आदि मेरे सवाल कर रहे हैं (वे दो हैं, लेकिन बहुत बारीकी से अलग सवाल हो से संबंधित):

  • लिनक्स कर्नेल कैसे काम करता है कि क्या ये फाइलें असली हैं (और इसलिए इन्हें डिस्क से पढ़ा जाता है) या नहीं जब एक रीड कमांड (या ऐसा) जारी किया जाता है?
  • यदि फ़ाइल वास्तविक नहीं है: उदाहरण के लिए, एक रीड से /dev/randomयादृच्छिक डेटा वापस आ जाएगा, और एक रीड से /dev/nullवापस आ जाएगा EOF। यह कैसे काम करता है कि इस वर्चुअल फ़ाइल से डेटा को कैसे पढ़ा जाए (और इसलिए वर्चुअल फ़ाइल में लिखे गए डेटा को कब / क्या करना है) या आभासी निर्देशिका के लिए भी? तो, एक प्रविष्टि के लिए /dev/nullबस वापस आ सकता है EOF

1
जब फ़ाइल बनाई जाती है, तो कर्नेल अपने प्रकार को रिकॉर्ड करता है। नियमित डिस्क फ़ाइलों को फिर सिमिलिंक, ब्लॉक डिवाइस, कैरेक्टर डिवाइस, डायरेक्टरी, सॉकेट, एफआईएफओ, आदि से अलग तरीके से व्यवहार किया जाता है। यह जानने के लिए कर्नेल का काम है।
जोनाथन लेफ़लर

मैनकॉड के लिए आदमी को देखें
जैसन

यह पूछने की तरह है "प्रकाश स्विच कैसे जानता है कि क्या प्रकाश चालू है?" प्रकाश स्विच यह तय करने के प्रभारी है कि प्रकाश चालू है या नहीं।
मोनिका

जवाबों:


25

तो यहाँ मूल रूप से दो अलग-अलग चीज़ें हैं:

  1. सामान्य filesystems, जो डेटा के साथ निर्देशिकाओं और मेटाडेटा में परिचित तरीके से फ़ाइलें रखती हैं, (नरम लिंक, हार्ड लिंक और इतने पर सहित)। ये अक्सर होते हैं, लेकिन हमेशा नहीं, लगातार भंडारण के लिए एक ब्लॉक डिवाइस द्वारा समर्थित (एक tmpfs केवल रैम में रहता है, लेकिन अन्यथा एक सामान्य फाइल सिस्टम के समान है)। इन के शब्दार्थ परिचित हैं; पढ़ना, लिखना, नाम बदलना और आगे बढ़ना, ये सभी उस तरह से काम करते हैं जैसे आप उनसे उम्मीद करते हैं।
  2. विभिन्न प्रकार के वर्चुअल फाइलसिस्टम। /procऔर /sysयहाँ उदाहरण हैं, जैसे FUSE कस्टम फाइल सिस्टम हैं जैसे sshfsया ifuse। इनमें बहुत अधिक विविधता है, क्योंकि वास्तव में वे सिर्फ एक फाइल सिस्टम को शब्दार्थ के साथ संदर्भित करते हैं जो कुछ अर्थों में हैं 'कस्टम'। इस प्रकार, जब आप किसी फ़ाइल के नीचे से पढ़ते हैं, तो आप /procवास्तव में डेटा के एक विशिष्ट टुकड़े तक नहीं पहुंच पाते हैं, जो कि सामान्य फ़ाइल सिस्टम के तहत कुछ और पहले इसे लिखते हुए संग्रहीत किया जाता है। आप अनिवार्य रूप से एक कर्नेल कॉल कर रहे हैं, जो कुछ सूचनाओं का अनुरोध करता है जो ऑन-द-फ्लाई उत्पन्न होती हैं। और यह कोड ऐसा कुछ भी कर सकता है जो इसे पसंद करता है, क्योंकि यह सिर्फ कुछ फ़ंक्शन है जो कहीं न कहीं readशब्दार्थ को लागू कर रहा है। इस प्रकार, आपके पास फ़ाइलों का अजीब व्यवहार है /proc, उदाहरण के लिए जब वे उठते हैं तो सहानुभूति का नाटक करते हैं '

कुंजी यह है कि /devवास्तव में, आमतौर पर, पहले प्रकार में से एक है। आधुनिक वितरणों में यह सामान्य /devहै कि एक tmpfs जैसा कुछ होना चाहिए, लेकिन पुराने सिस्टम में, बिना किसी विशेष विशेषता के डिस्क पर एक सादे निर्देशिका होना सामान्य था। कुंजी यह है कि फ़ाइल के नीचे /devडिवाइस नोड्स हैं, विशेष फाइल का एक प्रकार जो एफआईएफओ या यूनिक्स सॉकेट के समान है; डिवाइस नोड में एक प्रमुख और मामूली संख्या होती है, और उन्हें पढ़ना या लिखना एक कर्नेल ड्राइवर को कॉल कर रहा है, बहुत कुछ पढ़ने या लिखने की तरह एक पाइप में अपने आउटपुट को बफर करने के लिए कर्नेल को कॉल कर रहा है। यह ड्राइवर जो चाहे कर सकता है, लेकिन यह आमतौर पर किसी न किसी तरह से हार्डवेयर को छूता है, जैसे कि स्पीकर में हार्ड डिस्क या साउंड प्ले करने के लिए।

मूल सवालों के जवाब देने के लिए:

  1. 'फ़ाइल मौजूद है' या नहीं, इसके लिए प्रासंगिक दो प्रश्न हैं; ये हैं कि क्या डिवाइस नोड फ़ाइल शाब्दिक रूप से मौजूद है, और क्या यह कर्नेल कोड का समर्थन सार्थक है। पूर्व को एक सामान्य फाइलसिस्टम पर किसी भी चीज की तरह हल किया जाता है। आधुनिक सिस्टम udevहार्डवेयर घटनाओं को देखने के लिए इसका उपयोग करते हैं या कुछ ऐसा करते हैं और स्वचालित रूप से /devतदनुसार डिवाइस नोड्स बनाते और नष्ट करते हैं । लेकिन पुराने सिस्टम, या प्रकाश कस्टम बनाता है, बस डिस्क पर शाब्दिक रूप से बनाए गए उनके सभी डिवाइस नोड्स हो सकते हैं, समय से पहले। इस बीच, जब आप इन फ़ाइलों को पढ़ते हैं, तो आप कर्नेल कोड को कॉल कर रहे होते हैं जो प्रमुख और मामूली डिवाइस संख्याओं द्वारा निर्धारित किया जाता है; यदि ये उचित नहीं हैं (उदाहरण के लिए, आप एक ब्लॉक डिवाइस को पढ़ने की कोशिश कर रहे हैं जो मौजूद नहीं है), तो आपको किसी प्रकार का I / O त्रुटि मिलेगी।

  2. जिस तरह से यह पता चलता है कि किस डिवाइस फ़ाइल के लिए कर्नेल कोड कॉल करना है। जैसे वर्चुअल फाइलसिस्टम के लिए /proc, वे अपने स्वयं के readऔर writeकार्यों को लागू करते हैं ; कर्नेल बस उस कोड को कॉल करता है, जिसके आधार पर यह आरोह बिंदु है और फाइलसिस्टम कार्यान्वयन बाकी का ध्यान रखता है। डिवाइस फ़ाइलों के लिए, यह प्रमुख और मामूली डिवाइस नंबर के आधार पर भेजा जाता है।


तो अगर, मान लीजिए, एक पुरानी प्रणाली की शक्ति खींची गई थी, तो फाइलें /devअभी भी वहां मौजूद होंगी, लेकिन मुझे लगता है कि सिस्टम के शुरू होने पर वे साफ हो जाएंगे?
जो

2
यदि एक पुरानी प्रणाली (किसी भी गतिशील डिवाइस निर्माण के बिना) को सामान्य या असामान्य रूप से बंद कर दिया गया था, तो डिवाइस नोड्स किसी भी फाइल की तरह डिस्क पर बने रहेंगे। फिर जब अगला बूटअप हुआ, तो वे डिस्क पर भी बने रहेंगे, और आप उन्हें सामान्य रूप से उपयोग कर सकते हैं। यह केवल आधुनिक प्रणालियों में है कि डिवाइस नोड्स बनाने और नष्ट करने के लिए कुछ विशेष होता है।
टॉम हंट

तो एक और अधिक आधुनिक प्रणाली tmpfsगतिशील रूप से उपयोग नहीं कर रही है और उन्हें आवश्यकतानुसार हटा देगी, जैसे: बूटअप और शटडाउन?
जो

3
devtmpfs, /devआधुनिक लिनक्स में फाइलसिस्टम एक के समान है tmpfs, लेकिन समर्थन के लिए कुछ अंतर हैं udev। (कर्नेल udevबूट को कम जटिल बनाने के लिए बंद करने से पहले अपने आप कुछ स्वचालित नोड निर्माण करता है।) इन सभी मामलों में, डिवाइस नोड केवल रैम में रहते हैं और हार्डवेयर के रूप में गतिशील रूप से नष्ट हो जाते हैं और नष्ट हो जाते हैं। संभवतः आप udevएक साधारण ऑन-डिस्क पर भी उपयोग कर सकते हैं /dev, लेकिन मैंने ऐसा कभी नहीं देखा है और इसके लिए कोई भी अच्छा कारण नहीं है।
टॉम हंट

17

यहाँ /dev/sda1मेरे लगभग अप-टू-डेट आर्क लिनक्स सर्वर की फाइल लिस्टिंग है :

% ls -li /dev/sda1
1294 brw-rw---- 1 root disk 8, 1 Nov  9 13:26 /dev/sda1

तो निर्देशिका प्रविष्टि के /dev/लिए sdaएक इनकोड संख्या, 1294 है। यह डिस्क पर एक वास्तविक फ़ाइल है।

जहाँ फ़ाइल आकार आमतौर पर दिखाई देता है, उसे देखें। इसके बजाय "8, 1" दिखाई देता है। यह एक प्रमुख और मामूली डिवाइस नंबर है। फ़ाइल अनुमतियों में 'b' पर भी ध्यान दें।

फ़ाइल /usr/include/ext2fs/ext2_fs.hमें यह (टुकड़ा) सी संरचना शामिल है:

/*
 * Structure of an inode on the disk
 */
struct ext2_inode {
    __u16   i_mode;     /* File mode */

वह संरचना हमें फ़ाइल के इनोड की ऑन-डिस्क संरचना दिखाती है। दिलचस्प सामान का बहुत कुछ उस संरचना में है; इस पर एक लंबी नज़र डालें।

i_modeके तत्व struct ext2_inode16 बिट है, और यह उपयोगकर्ता / समूह / अन्य के लिए केवल 9 का उपयोग करता है, पढ़ने / लिखने / निष्पादित अनुमतियाँ, और setuid, setgid, और चिपचिपा के लिए एक और 3। इसे "सादा फ़ाइल", "लिंक", "निर्देशिका", "नामित पाइप", "यूनिक्स परिवार सॉकेट", और "ब्लॉक डिवाइस" जैसे प्रकारों में अंतर करने के लिए 4 बिट्स मिले हैं।

लिनक्स कर्नेल सामान्य निर्देशिका लुकअप एल्गोरिथ्म का पालन कर सकता है, फिर i_modeतत्व में अनुमतियों और झंडे के आधार पर निर्णय ले सकता है। 'बी' के लिए, डिवाइस फ़ाइलों को ब्लॉक करें, यह प्रमुख और मामूली डिवाइस नंबर पा सकता है, और परंपरागत रूप से, डिस्क के साथ काम करने वाले कुछ कर्नेल फ़ंक्शन (एक डिवाइस ड्राइवर) के लिए सूचक को देखने के लिए प्रमुख डिवाइस नंबर का उपयोग करता है। माइनर डिवाइस नंबर आमतौर पर एससीएसआई बस डिवाइस नंबर, या ईआईडी डिवाइस नंबर या ऐसा ही कुछ कहा जाता है।

/proc/cpuinfoफाइल के प्रकार से निपटने के तरीके के बारे में कुछ अन्य निर्णय फाइलसिस्टम प्रकार के आधार पर किए जाते हैं। यदि आप एक:

% mount | grep proc 
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)

आप देख सकते हैं कि /procफ़ाइल सिस्टम का प्रकार "proc" है। फ़ाइल /procके प्रकार के आधार पर फ़ाइल को पढ़ने से फ़ाइल सिस्टम के प्रकार के आधार पर कुछ अलग किया जा सकता है, जिस तरह एक ReiserFS या DOS फ़ाइल सिस्टम पर फ़ाइल खोलने से कर्नेल को फ़ाइलों का पता लगाने और डेटा का पता लगाने के लिए विभिन्न कार्यों का उपयोग करना होगा। फ़ाइलें।


क्या आप निश्चित हैं, कि केवल "डिस्क पर वास्तविक फ़ाइलें" में एक इनोड नंबर प्रदर्शित होता है? मुझे लगता है 4026531975 -r--r--r-- 1 root root 0 Nov 14 18:41 /proc/mdstatजो स्पष्ट रूप से एक "वास्तविक फ़ाइल" नहीं है।
गुंटबर्ट

7

दिन के अंत में वे यूनिक्स के लिए सभी फाइलें हैं, जो कि अमूर्तता की सुंदरता है।

जिस तरह से फाइल को कर्नेल द्वारा संभाला जाता है, अब वह एक अलग कहानी है।

/ proc और आजकल / dev और / run (aka / var / run) रैम में वर्चुअल फाइलसिस्टम हैं। / proc कर्नेल चर और संरचनाओं के लिए एक इंटरफ़ेस / विंडो है।

मैं लिनक्स कर्नेल http://tldp.org/LDP/tlk/tlk.html और लिनक्स डिवाइस ड्राइवर, तीसरा संस्करण https://lwn.net/Kernel/LDD3/ पढ़ने की सलाह देता हूं ।

मैं भी डिजाइन और FreeBSD ऑपरेटिंग सिस्टम का कार्यान्वयन का आनंद लिया http://www.amazon.com/Design-Implementation-FreeBSD-Operating-System/dp/0321968972/ref=sr_1_1

संबंधित पृष्ठ पर एक नज़र डालें जो आपके प्रश्न से संबंधित है।

http://www.tldp.org/LDP/tlk/dd/drivers.html


धन्यवाद, मैंने आपके द्वारा टिप्पणी करने के बाद पहला प्रश्न थोड़ा बदल दिया है।
जो

कृपया अंतिम टिप्पणी पढ़ें।
रुई एफ रिबेरो

5

@ RuiFRibeiro's और @ BruceEdiger के उत्तरों के अलावा, आप जो अंतर करते हैं, वह वास्तव में वह अंतर नहीं है जो कर्नेल बनाता है। वास्तव में, आपके पास विभिन्न प्रकार की फाइलें हैं: नियमित फाइलें, निर्देशिकाएं, प्रतीकात्मक लिंक, डिवाइस, सॉकेट (और मैं हमेशा कुछ भूल जाता हूं इसलिए मैं पूरी सूची बनाने की कोशिश नहीं करूंगा)। आपके पास फ़ाइल के प्रकार की जानकारी हो सकती है ls: यह लाइन का पहला वर्ण है। उदाहरण के लिए:

$ls -la /dev/sda
brw-rw---- 1 root disk 8, 0 17 nov.  08:29 /dev/sda

बहुत शुरुआत में 'बी' संकेत देता है कि यह फ़ाइल एक ब्लॉक डिवाइस है। पानी का छींटा, एक नियमित फ़ाइल का अर्थ है, 'एल' एक प्रतीकात्मक लिंक और इसी तरह। यह जानकारी फ़ाइल के मेटाडेटा में संग्रहीत है, और statउदाहरण के लिए सिस्टम कॉल के माध्यम से सुलभ है , इसलिए कर्नेल को एक फ़ाइल और उदाहरण के लिए एक प्रतीकात्मक लिंक पढ़ सकते हैं।

फिर, आप "वास्तविक फ़ाइलों" /bin/bashऔर "आभासी फ़ाइलों" के बीच एक और अंतर करते हैं , /proc/cpuinfoलेकिन जैसे lsदोनों नियमित फ़ाइलों के रूप में रिपोर्ट करते हैं, इसलिए अंतर दूसरे प्रकार का है:

ls -la /proc/cpuinfo /bin/bash
-rwxr-xr-x 1 root root  829792 24 août  10:58 /bin/bash
-r--r--r-- 1 root wheel      0 20 nov.  16:50 /proc/cpuinfo

क्या होता है कि वे विभिन्न फाइल सिस्टम से संबंधित हैं। /procएक छद्म फाइलसिस्टम का बढ़ते बिंदु है, procfsजबकि /bin/bashएक नियमित डिस्क फाइलसिस्टम पर है। जब लिनक्स एक फाइल खोलता है (यह फाइलसिस्टम पर निर्भर करता है तो अलग-अलग करता है), यह एक डेटा संरचना को पॉप्युलेट करता है fileजो अन्य विशेषताओं के बीच कई फ़ंक्शन पॉइंटर्स की एक संरचना को बताता है जो इस फाइल का उपयोग करने के तरीके का वर्णन करता है। इसलिए, यह विभिन्न प्रकार की फ़ाइलों के लिए अलग-अलग व्यवहार को लागू कर सकता है।

उदाहरण के लिए, ये /proc/meminfoनिम्न द्वारा विज्ञापित कार्य हैं :

static int meminfo_proc_open(struct inode *inode, struct file *file)
{
    return single_open(file, meminfo_proc_show, NULL);
}

static const struct file_operations meminfo_proc_fops = {
    .open       = meminfo_proc_open,
    .read       = seq_read,
    .llseek     = seq_lseek,
    .release    = single_release,
};

यदि आप की परिभाषा को meminfo_proc_openदेखते हैं, तो आप देख सकते हैं कि यह फ़ंक्शन फ़ंक्शन द्वारा दी गई जानकारी के साथ मेमोरी में एक बफर को पॉप्युलेट करता है meminfo_proc_show, जिसका कार्य मेमोरी उपयोग के बारे में डेटा एकत्र करना है। यह जानकारी तब सामान्य रूप से पढ़ी जा सकती है। हर बार जब आप फ़ाइल खोलते हैं, तो फ़ंक्शन meminfo_proc_openको कॉल किया जाता है और मेमोरी के बारे में जानकारी ताज़ा हो जाती है।


3

फ़ाइल सिस्टम की सभी फाइलें इस मायने में "वास्तविक" हैं कि वे फ़ाइल I / O की अनुमति देते हैं। जब आप कोई फ़ाइल खोलते हैं, तो कर्नेल एक फ़ाइल डिस्क्रिप्टर बनाता है, जो एक ऑब्जेक्ट (ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग के अर्थ में) है जो एक फ़ाइल की तरह कार्य करता है। यदि आप फ़ाइल पढ़ते हैं, तो फ़ाइल डिस्क्रिप्टर इसकी रीड मेथड को निष्पादित करता है, जो बदले में फाइल से डेटा के लिए फाइल सिस्टम (sysfs, ext4, nfs, आदि) पूछेगा। फाइल सिस्टम यूजर्स के लिए एक समान इंटरफेस प्रस्तुत करता है, और पता है कि रीड और राइट को हैंडल करने के लिए क्या करना है। बदले में फाइल सिस्टम अन्य परतों को उनके अनुरोधों को संभालने के लिए कहता है। एक्स्ट 4 फाइल सिस्टम पर एक नियमित फाइल के लिए, इसमें फाइल सिस्टम के डेटा स्ट्रक्चर्स (जिसमें डिस्क रीड शामिल हो सकता है) में लुक अप शामिल होगा, और अंततः डिस्क (या कैश) से रीड रीड बफर में डेटा कॉपी करना शामिल होगा। फ़ाइल में sysfs के लिए, यह आम तौर पर सिर्फ स्प्रिंटफ () बफर के लिए कुछ है। एक ब्लॉक देव नोड के लिए, यह डिस्क ड्राइवर को कुछ ब्लॉकों को पढ़ने और उन्हें बफर में कॉपी करने के लिए कहेगा (प्रमुख और छोटी संख्या फ़ाइल सिस्टम को बताती है कि किस ड्राइवर को अनुरोध करना है)।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.