2009-07-26 9 views
73

मैं सभी चर्चाओं को जानता हूं कि किसी को कर्नेल से फ़ाइलों को क्यों नहीं पढ़ना/लिखना चाहिए, इसके बजाय इसे करने के लिए/proc या netlink का उपयोग कैसे करें। मैं वैसे भी पढ़ना/लिखना चाहता हूं। मैंने Driving Me Nuts - Things You Never Should Do in the Kernel भी पढ़ा है।लिनक्स कर्नेल मॉड्यूल के भीतर फ़ाइलों को कैसे पढ़/लिखना है?

हालांकि, समस्या 2.6.30 sys_read() निर्यात नहीं करता है। इसके बजाय इसे SYSCALL_DEFINE3 में लपेटा गया। तो अगर मैं का उपयोग करें कि मेरी मॉड्यूल में, मैं निम्नलिखित चेतावनी मिलती है: क्योंकि जोड़ने सही ढंग से नहीं होता है

WARNING: "sys_read" [xxx.ko] undefined! 
WARNING: "sys_open" [xxx.ko] undefined! 

जाहिर insmod मॉड्यूल लोड नहीं कर सकता।

सवाल:

  • कैसे पढ़ने के लिए 2.6.22 (जहां sys_read()/sys_open() निर्यात नहीं कर रहे हैं) के बाद गिरी भीतर/लिखने?
  • सामान्य रूप से, कर्नेल के भीतर से मैक्रो SYSCALL_DEFINEn() में लिपटे सिस्टम कॉल का उपयोग कैसे करें?

उत्तर

94

आपको अवगत होना चाहिए कि जब संभव हो तो आपको फ़ाइल I/O से बचना चाहिए।

शामिल हैं::

#include <linux/fs.h> 
#include <asm/segment.h> 
#include <asm/uaccess.h> 
#include <linux/buffer_head.h> 

एक फ़ाइल (खोलने के लिए समान) खुलने:

struct file *file_open(const char *path, int flags, int rights) 
{ 
    struct file *filp = NULL; 
    mm_segment_t oldfs; 
    int err = 0; 

    oldfs = get_fs(); 
    set_fs(get_ds()); 
    filp = filp_open(path, flags, rights); 
    set_fs(oldfs); 
    if (IS_ERR(filp)) { 
     err = PTR_ERR(filp); 
     return NULL; 
    } 
    return filp; 
} 

मुख्य विचार जाने के लिए "एक स्तर गहरा" और सीधे syscall हैंडलर के बजाय VFS level functions कहते हैं एक फ़ाइल बंद करें (करीब के समान):

void file_close(struct file *file) 
{ 
    filp_close(file, NULL); 
} 

किसी फ़ाइल से डेटा पढ़ना (prea के समान घ): एक फाइल करने के लिए

int file_read(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size) 
{ 
    mm_segment_t oldfs; 
    int ret; 

    oldfs = get_fs(); 
    set_fs(get_ds()); 

    ret = vfs_read(file, data, size, &offset); 

    set_fs(oldfs); 
    return ret; 
} 

डेटा लेखन (pwrite के समान):

int file_write(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size) 
{ 
    mm_segment_t oldfs; 
    int ret; 

    oldfs = get_fs(); 
    set_fs(get_ds()); 

    ret = vfs_write(file, data, size, &offset); 

    set_fs(oldfs); 
    return ret; 
} 

सिंक्रनाइज़ किए जा रहे एक फ़ाइल (fsync के समान) परिवर्तन:

int file_sync(struct file *file) 
{ 
    vfs_fsync(file, 0); 
    return 0; 
} 

[संपादित करें] मूल रूप से, मैंने file_fsync का उपयोग करने का प्रस्ताव दिया है, जो कि नए कर्नेल संस्करणों में चला गया है। परिवर्तन का सुझाव देने वाले गरीब व्यक्ति के लिए धन्यवाद, लेकिन जिसका परिवर्तन अस्वीकार कर दिया गया था। इससे पहले कि मैं इसकी समीक्षा कर सकूं, संपादन को खारिज कर दिया गया था।

+2

धन्यवाद। मैं sys_read/sys_open कार्यक्षमता को दोहराने के समान कुछ करने की सोच रहा था। लेकिन यह बहुत मददगार है। एक जिज्ञासा, SYSCALL_DEFINE का उपयोग करके घोषित सिस्टम कॉल का उपयोग करने का कोई तरीका है? – Methos

+5

मैंने कर्नेल 2.6.30 (उबंटू 9.04) में इस कोड को आजमाया और फ़ाइल को पढ़ने से सिस्टम को क्रैश हो गया। किसी को भी एक ही समस्या का अनुभव किया? –

+0

@ एन्रिको डेटोमा? ओह वाह। क्या यह कोई तरीका है कि आप मुझे इस्तेमाल मॉड्यूल दे सकते हैं? पहले कभी नहीं देखा? – dmeister

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