2012-05-09 19 views
8

मुझे पता है कि copy_to_user/copy_from_user, get_user/put_user फ़ंक्शंस इस उद्देश्य के लिए हैं।लिनक्स कर्नेल से उपयोगकर्ता स्पेस मेमोरी तक कैसे पहुंचे?

मेरा सवाल यह है कि, उपयोगकर्ता स्पेस पता/पॉइंटर दिया गया है, मैं सामान्य रूप से कर्नेल से पते द्वारा इंगित डेटा तक कैसे पहुंच सकता हूं?

मैं कल्पना कर सकता हूं कि पहले मुझे यह सुनिश्चित करना होगा कि युक्त पृष्ठ भौतिक स्मृति (डिस्क में की बजाय) में होना चाहिए।

अगला कदम क्या है? क्या मैं *p का उपयोग कर सकता हूं, जहां p कुछ उपयोगकर्ता स्थान डेटा को इंगित करने वाला पॉइंटर है, सीधे डेटा को संदर्भित करने के लिए?

या क्या मुझे कर्नेल वर्चुअल एड्रेस स्पेस में युक्त भौतिक पृष्ठ फ्रेम को मैप करने के लिए पहले kmap का उपयोग करना होगा? क्यूं कर?

उत्तर

4

अकेले सूचक पर्याप्त नहीं है! आपको यह जानने की ज़रूरत है कि कौन सी प्रक्रिया पॉइंटर "संबंधित" है।

जब प्रक्रिया को छूट दी जाती है, तो पॉइंटर किसी अन्य प्रक्रिया के पता स्थान में इंगित करता है। पते को और भी मैप नहीं किया जा सकता है, yadda yadda,

यदि डेटा तक पहुंचने पर यह प्रक्रिया वर्तमान प्रक्रिया होगी, तो आपको copy_to_user/copy_from_user फ़ंक्शंस का उपयोग करना चाहिए।

यदि प्रक्रिया निर्धारित की जा सकती है, तो आप रैम में पृष्ठ को mlock() करने का प्रयास कर सकते हैं और यह पता लगा सकते हैं कि पृष्ठ का भौतिक राम पता कौन सा है। जब भी आप इसे एक्सेस करना चाहते हैं, तो आप उस भौतिक पृष्ठ को कर्नेल वर्चुअल एड्रेस में मैप करते हैं।

नोट:

  • एक दुर्भावनापूर्ण प्रक्रिया (munlock कर सकते हैं) पेज और एक गलत रैम पेज तक पहुँचने के लिए आपको धोखा।
  • मुझे यकीन नहीं है कि mlock() अर्थशास्त्र की मांग है कि रेड पेज को रेखांकित करना आवश्यक नहीं है।
  • कर्नेल किसी पृष्ठ को रैम में लॉक करने में सक्षम होना चाहिए, मैं एमएम उपप्रणाली से परिचित नहीं हूं।
3

विभिन्न उपयोगकर्ता स्थान एप्लिकेशन में अलग-अलग पृष्ठ तालिका होती है। 1) आपको उपयोगकर्ता स्पेस प्रोग्राम पिड प्राप्त करने की आवश्यकता है। 2) पिड की पेज तालिका में खोज जोड़ें।

नीचे उपयोगकर्ता स्थान वर्चुअल एड्रेस को भौतिक पते में अनुवाद करने के लिए नमूना कोड है। यह x86 प्लेटफॉर्म पर काम करता है।

taskpid = find_get_pid(curpid); 
task = pid_task(taskpid, PIDTYPE_PID); 
mm = get_task_mm(task); 
down_read(&mm->mmap_sem); 

start_vaddr = vaddr; 
end_vaddr = 0xC0000000; 

while(start_vaddr < end_vaddr){ 
    u32 end; 

    end = ((start_vaddr + PMD_SIZE) & PMD_MASK); 

    if(end < start_vaddr || end > end_vaddr) 
     end = end_vaddr; 

    ret = walk_pgd(start_vaddr, end, mm); 
    if(ret != 0){ 
     printk("ret: %08x \n", ret); 
     break; 
    } 

    start_vaddr = end; 

} 

up_read(&mm->mmap_sem); 

paddr = ret; 
kaddr = __va(paddr); 
mmput(mm); 
+0

अच्छा बिंदु और कोड तर्क अच्छा है। लेकिन मुझे लगता है कि कुछ हैश टेबल या समान डेटा संरचना है, जिसे वर्चुअल एड्रेस दिया गया है, आपको भौतिक पृष्ठ को तुरंत ढूंढने में मदद करता है। एक दोष है: kaddr = __va (पैडर); यह पंक्ति केवल तभी काम करती है जब पैडर कम स्मृति में रहता है, है ना? – Infinite

+0

पैड्रर का अर्थ भौतिक पता है, इसलिए, हमेशा स्मृति में मौजूद होता है। कैडर का मतलब कर्नेल पता है। लिनक्स कर्नेल परिभाषित में '# परिभाषित __va (x) ((शून्य *) ((हस्ताक्षर किए गए लंबे) (x) + PAGE_OFFSET)) '। कर्नेल पता मेमोरी मैपिंग जटिल नहीं है, केवल एक PAGE_OFFSET है। (X86 मोड पर 0xC0000000 होना चाहिए)। पता पाने का दूसरा तरीका है। उपयोगकर्ता जानकारी एप्लिकेशन पृष्ठ जानकारी प्राप्त करने के लिए/proc//पेजमैप के साथ कर्नेल पते तक पहुंच सकता है। अगर पीएफएन प्राप्त हो सकता है, तो यह कर्नेल पता भी प्राप्त कर सकता है। – richliu

0

आप follow के लिए एक भाषण जरूरत है एक इसी page struct (उदाहरण के लिए follow_page देखें) प्राप्त करने के लिए होगा। इसके बाद, page संरचना प्राप्त करने के लिए आपको इसे kmap या kmap_atomic के माध्यम से कर्नेल के पता स्थान पर मैप करने की आवश्यकता होगी।

3

आपको यह उपयोगी मिल सकता है।

आइए दोहराएं कि पढ़ने और लिखने के तरीकों के लिए बफ तर्क उपयोगकर्ता-स्थान सूचक है। इसलिए, इसे सीधे कर्नेल कोड द्वारा संदर्भित नहीं किया जा सकता है।

  • निर्भर करता है जो वास्तुकला पर अपने ड्राइवर पर चल रहा है, और कैसे गिरी कॉन्फ़िगर किया गया था, उपयोगकर्ता के अंतरिक्ष सूचक जबकि पर गिरी मोड में चल रहा मान्य न हो: इस प्रतिबंध के लिए कुछ कारण हैं सब। उस पते के लिए कोई मैपिंग नहीं हो सकती है, या यह किसी अन्य, यादृच्छिक डेटा को इंगित कर सकती है।

  • यहां तक ​​कि अगर सूचक गिरी अंतरिक्ष में एक ही बात का क्या मतलब है, उपयोगकर्ता के अंतरिक्ष स्मृति पृष्ठांकित है, और प्रश्न में स्मृति रैम में निवासी नहीं हो सकता है जब सिस्टम कॉल किया जाता है। संदर्भ देने का प्रयास करने से उपयोगकर्ता-स्पेस मेमोरी सीधे पेज गलती उत्पन्न कर सकती है, जो कि है जो कर्नेल कोड को करने की अनुमति नहीं है। नतीजा होगा "ओह," जिसके परिणामस्वरूप सिस्टम कॉल की प्रक्रिया की मृत्यु होगी।

  • प्रश्न में सूचक उपयोगकर्ता प्रोग्राम द्वारा प्रदान किया गया है, जो छोटी या दुर्भावनापूर्ण हो सकता है। यदि आपका चालक कभी भी उपयोगकर्ता द्वारा आपूर्ति किए गए पॉइंटर को अंधाधुंध रूप से अस्वीकार करता है, तो यह उपयोगकर्ता-स्पेस प्रोग्राम को सिस्टम में कहीं भी स्मृति तक पहुंचने या ओवरराइट करने की अनुमति देता है। यदि आप अपने उपयोगकर्ताओं के सिस्टम की सुरक्षा से समझौता करने के लिए ज़िम्मेदार नहीं होना चाहते हैं, तो आप कभी भी उपयोगकर्ता-स्थान सूचक सीधे अस्वीकार नहीं कर सकते हैं।

स्रोत: http://www.makelinux.net/ldd3/chp-3-sect-7

जिसके अनुसार, मैं अपने आप को पता करने के लिए क्या होता है उपयोगकर्ता के अंतरिक्ष का पता वास्तव में वैध है, और इसके बाद के संस्करण की स्थिति भी नहीं लागू होगा अगर उत्सुक हूँ ...

संबंधित मुद्दे