मैं ioctl
सी ++ से उस ड्राइवर में कॉल कर रहा हूं जिसमें मेरा स्वामित्व/रखरखाव नहीं है, और यदि कोई साफ, "सुरक्षित-आश" तंत्र है तो मैं इसे हल करने का प्रयास कर रहा हूं कुछ बदसूरत संरचना आवंटन के साथ निपटने के लिए आवश्यक है। कुछ संरचनाओं केबदसूरत सी संरचना आवंटन के लिए आधुनिक सी ++ पैटर्न
नीचे Slimmed संस्करण शामिल
// IOCTL expects an instance of this structure "first"
typedef struct {
int param1;
int param2;
} s_ioctl_request;
//... followed by an instance of this. If attr_length
// is > sizeof(s_attr_header), more data is allowed to follow.
typedef struct {
uint32_t attr_length;
uint32_t attr_type;
} s_attr_header;
// Example that uses more data than just the header.
typedef struct {
s_attr_header hdr;
uint32_t attr_param;
} s_attr_type1;
// Another example.
typedef struct {
s_attr_header hdr;
uint32_t attr_param1;
uint32_t attr_param2;
} s_attr_type2;
ioctl की आवश्यकता है कि s_ioctl_request
तुरंत एक s_attr_header
द्वारा पालन किया जाना, या अन्य struct यह युक्त, जहां attr_length
बाइट में बाहरी struct के आकार को तैयार है।
C
में, ioctl
के लिए एक आवरण लिखने के लिए यह इन पंक्तियों के साथ कुछ के माध्यम से किया जाएगा:
int do_ugly_ioctl(int fd, int p1, int p2, s_attr_header * attr)
{
int res;
// Allocate enough memory for both structures.
s_ioctl_request *req = malloc(sizeof(*req) + attr->hdr.attr_length);
// Copy the 2nd, (variable length) structure after the first.
memcpy(((char*)req) + sizeof(*req), attr, attr->hdr.attr_length);
// Modify params as necessary
req->param1 = p1;
req->param2 = p2;
// Make the driver call, free mem, and return result.
res = ioctl(fd, SOME_IOCTL_ID, req);
free(req);
return res;
}
// Example invocation.
s_attr_type1 a1;
a1.hdr.attr_length = sizeof(a1);
a1.hdr.attr_type = 1;
do_ugly_ioctl(fd, 10, 20, &a1);
एक जोड़े विकल्प के बारे में सोच रहा हूँ, कर रहे हैं:
फेंक आधुनिक सी ++ - खिड़की से बाहर निकलता है, और ठीक वही करता है जो मैंने ऊपर दिखाया है।
एक std :: वेक्टर के साथ भंडारण का आवंटन, तो जिसके परिणामस्वरूप std :: वेक्टर :: डेटा() सूचक के साथ बदसूरत डाले तो कम से कम मैं
new[]
/delete[]
याmalloc
/free
नहीं कर रहा हूँ है।प्रत्येक
s_attr_type*
के लिए एक अद्वितीय रैपर विधि बनाएं जो अपनी "विशेष" संरचना का उपयोग करती है। यह "सुरक्षित" लगता है, यानी इसे लपेटने के लिए रैपर विधि के उपयोगकर्ता के लिए कम से कम संभावना है। और बोनस अंक, पास-दर-रेफरी की अनुमति देता है।
विधि # 3 उदाहरण:
int do_ugly_ioctl(fd, int param1, int param2, s_attr_type2& attr){
struct RequestData {
s_ioctl_request ioreq;
s_attr_type2 attr;
};
RequestData r;
r.ioreq.param1 = param1;
r.ioreq.param2 = param2;
r.attr = attr;
r.attr.hdr.attr_length = sizeof(attr); // Might as well enforce this here.
ioctl(fd, SOME_IOCTL_ID, (void*) &r);
}
तो मैं कुछ सवाल यहाँ लगता है कि कर रहे हैं:
यह सेल्सियस तक ++ "इसके लायक" है - इस समस्या का समाधान ize? (जैसा कि अधिक त्रुटि प्रवण सी प्रत्यारोपण पर निर्भर करने के विरोध में)।
यदि मैं विधि # 3 या इसी तरह के साथ जाता हूं, तो क्या मैं इस कार्य का टेम्पलेट बनाने के लिए
<type_traits>
के साथ कुछ भी कर सकता हूं और केवल पहले सदस्य के रूप मेंs_attr_header
के साथ structs स्वीकार करता हूं?कोई अन्य शानदार विचार?
सी रैपर को कोड की 8 लाइनों की आवश्यकता होती है। सी ++ रैपर की आवश्यकता है 10. मैं ज्यादा सुधार देखने में विफल रहता हूं। –
विकल्प 2 सिर्फ std :: वेक्टर के अंदर आवंटन छुपा रहा है, इसलिए इसमें कोई सुधार नहीं है। वास्तव में, विकल्प 2 एक भयानक समाधान है। –
@CareyGregory मैं नहीं कहूंगा कि यह छिपा हुआ है क्योंकि प्रत्येक सी ++ - प्रोग्रामर जानता है कि वेक्टर क्या करता है। यह इसे encapsulated कहते हैं। – Jens