2016-11-22 9 views
5

जहां तक ​​मुझे पता है, ioctl() उपयोगकर्ताओं के अनुप्रयोगों के लिए "विस्तारित" सिस्टम कॉल इंटरफ़ेस का पर्दाफाश करने के लिए उपयोग किया जाता है। विशिष्ट ड्राइवरों के लिए अद्वितीय हजारों सिस्टम कॉल जोड़ने के बजाय, ioctl() का उपयोग एकल सिस्टम कॉल के माध्यम से एक्स्टेंसिबल ड्राइवर-विशिष्ट फ़ंक्शंस प्रदान करने के लिए किया जाता है।ioctl() और कर्नेल हेडर पर भ्रम

यह पर्याप्त स्पष्ट लगता है। हालांकि, मैं अपना पहला एप्लिकेशन संकलित करने की कोशिश कर रहा हूं जो ioctl() कॉल का उपयोग करता है, और मुझे अपनी समझ पर संदेह करना शुरू हो रहा है।

विशेष रूप से, मैं एक ioctl() एक ईएमएमसी डिवाइस को "sanitize" करने के लिए कॉल करना चाहता हूं। /usr/include/linux/mmc/ioctl.h पर एक नज़र ले रहा है (या include/uapi/linux/mmc/ioctl.h पर गिरी स्रोत में), मैं इस संरचना देख सकते हैं:

struct mmc_ioc_cmd { 
     // Most fields omitted 
     int write_flag;  
     __u32 opcode; 
     __u32 arg; 
}; 

यूज़रस्पेस से, मैं इस हेडर सहित और मेरे ioctl() कॉल में इस संरचना गुजर किसी भी मुद्दे नहीं है।

तो यह मेरा अंतिम स्वच्छ स्निपेट ऐसा दिखता है क्या है:

int sanitize(int fd) 
{ 
    struct mmc_ioc_cmd command; 
    memset(&command, 0, sizeof(command)); 

    command.write_flag = 1; 
    command.opcode = MMC_SWITCH; 
    command.arg = EXT_CSD_SANITIZE_START << 16; 

    return ioctl(fd, MMC_IOC_CMD, &command); 
} 

मेरे समस्या यह है कि MMC_SWITCH और EXT_CSD_SANITIZE_START दोनों कर्नेल हेडर में निर्धारित किए जाते हैं। विशेष रूप से, मेरे कर्नेल स्रोत में, वे दोनों include/linux/mmc/mmc.h पर पाए जाते हैं।

इंटरनेट पर जो कुछ भी मैंने देखा है, में उपयोगकर्ता स्पेस प्रोजेक्ट बनाने के दौरान कर्नेल स्रोत से शीर्षलेख शामिल हैं। यदि ऐसा है, तो आप एमएमसी ioctl() का उचित रूप से उपयोग कैसे कर सकते हैं? कर्नेल संरचना को ioctl() में पास करने के लिए खुलासा करता है, लेकिन ऐसा लगता है कि आप केवल कर्नेल स्रोत में छिपे हुए "छिपा" स्थिरांक के साथ इसे भरकर संरचना का उपयोग कर सकते हैं।

मेरा वर्तमान समाधान कर्नेल हेडर से आवश्यक परियोजनाओं को प्रतिलिपि बनाना है, लेकिन यह मेरे लिए गंदा लगता है।

क्या मैं ioctl() के लिए उपयोग-केस को गलत समझ रहा हूं? क्या यह एक डिजाइन निरीक्षण है?

+0

FWIW, [mmc-utils] के स्रोत [http://git.kernel.org/cgit/linux/kernel/git/cjb/mmc-utils.git/) में स्वयं का शामिल है कर्नेल हेडर से प्राप्त हेडर। –

उत्तर

2

MMC_IOC_CMD ioctl, और इसी mmc_ioc_cmd संरचना, लिनक्स यूज़रस्पेस एपीआई का हिस्सा हैं, और इसलिए uapi हेडर कि /usr/include में स्थापित कर रहे हैं में परिभाषित कर रहे हैं।

आपके द्वारा opcode फ़ील्ड में डाला गया मान सीधे डिवाइस पर भेजा जाता है। कर्नेल वास्तव में इसकी परवाह नहीं करता है, और यह गारंटी नहीं दे सकता कि डिवाइस किस ऑपोड्स का समर्थन करता है, या यह किसी विशिष्ट ऑपोड के लिए कैसे व्यवहार करता है।इसलिए, MMC_SWITCH जैसे opcodes एपीआई का हिस्सा नहीं हैं।

जहाँ तक मैं देख सकता हूं, आपको प्रासंगिक एमएमसी मानकों से ऑपकोड प्राप्त करना होगा।

(यह प्रतीक वास्तव में उपयोगकर्ता-स्थान एपीआई से बाहर रखने का एक अच्छा कारण नहीं है; कर्नेल हेडर की प्रतिलिपि मानक से मूल्यों को मैन्युअल रूप से ट्रांसक्रिप्ट करने से कहीं अधिक आसान है। और कर्नेल में वास्तव में हैंडलिंग के लिए एक विशेष मामला है EXT_CSD_SANITIZE_START इस ioctl के माध्यम से।)

1

यदि आप #include को बिना किसी अतिरिक्त -I जोड़कर अपने जीसीसी कमांड लाइन पर पथ शामिल कर सकते हैं, तो आप ठीक हैं।

सब कुछ मैं इंटरनेट पर देखा है का कहना है कि करने के लिए नहीं जब यूज़रस्पेस परियोजनाओं के निर्माण गिरी स्रोत से शीर्षक शामिल करें।

उस सलाह का मतलब है कि कर्नेल स्रोत पेड़ से सीधे हेडर शामिल नहीं हैं। uapi शीर्षलेख उपयोगकर्ताओं के स्थान से उपभोग किए जाने का इरादा रखते हैं, और /usr/include में स्थापित किए गए हैं।

+0

यह सही मामला नहीं है। 'लिनक्स/एमएमसी/ioctl.h' एक' यूपीआई 'हैडर है और इसका खुलासा किया गया है। यह मुझे 'mmc_ioc_cmd' की परिभाषा देखने देता है। समस्या यह है कि, 'mmc_ioc_cmd' इसके क्षेत्रों में जाने वाले स्थिरांक/मैक्रोज़ को जानने के बिना व्यर्थ है। ये * नहीं * 'यूपीआई हेडर हैं (वे 'शामिल/लिनक्स/एमएमसी/एमएमसीएचएच' में हैं - 'यूपीआई' की कमी पर ध्यान दें), इसलिए मुझे अपने कर्नेल स्रोत को विशेष रूप से जीसीसी को इंगित करने की आवश्यकता होगी उन्हें देख। –

+0

@ मैट: ऐसा लगता है जैसे यह कर्नेल के साथ एक मुद्दा हो सकता है। क्या आपने उस उपप्रणाली के रखरखाव को पूछने के लिए ईमेल किया है? – dave

+0

@ डेव: मैंने नहीं किया है। मैं कर्नेल में ज्यादा समय नहीं बिताता, इसलिए मैंने सोचा कि मैं सुनिश्चित करूँगा कि मैं रखरखाव को बांधने से पहले 'ioctl()' को गलत समझ नहीं रहा हूं। यह एक अच्छा अगला कदम की तरह लगता है। –

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