2017-01-29 5 views
5

मान लें कि मेरे पास एक बाहरी डिवाइस है जो लगातार मेरे ड्राइवर में डेटा को एक छोटे बफर में दबा रहा है। मैं एक प्रतीक्षा कतार का उपयोग कर रहा हूं जहां एक इंटरप्ट हैंडलर एक प्रतीक्षा उपयोगकर्ता प्रक्रिया (एलडीडी (तीसरा संस्करण) के समान - एक हैंडलर लागू करना)।लिनक्स डिवाइस ड्राइवर बफरिंग रणनीति

irq_handler_t irq_handler(int irq, void *dev_id, struct pt_regs *regs) 
{ 

flag = 1; 
wake_up_interruptible(&wq); 

return IRQ_HANDLED; 
} 

ssize_t my_read(struct file *dev, char __user *buf, size_t count, loff_t *f_pos) 

{ 

     wait_event_interruptible(wq, flag != 0); 
     flag = 0; 
     copy_to_user(usr_buf, drv_buf, count); 

} 


/***********************User program***********************/ 

while(1) 
{  
    read(fid, buffer, size); 

    //do stuff with data 

} 

उपयोगकर्ता प्रोग्राम पढ़ता है और यह तब तक प्रतीक्षा करता है जब तक कि बाधा बाहरी डिवाइस से नया डेटा न हो जाए। चूंकि बाहरी डिवाइस इस कोड को निष्पादित करने से तेज़ डेटा को धक्का दे सकता है, इसलिए उपयोगकर्ता प्रोग्राम की प्रतिलिपि बनाने से पहले डेटा को ओवरराइट नहीं किया गया है, यह सुनिश्चित करने के लिए मैं किस तंत्र का उपयोग कर सकता हूं? क्या रिंग बफर संरचना की तरह काम करेगा? यह स्पष्ट नहीं है कि इसे कैसे कार्यान्वित किया जाए।

धन्यवाद

+0

आपके drv_buf को डेटा कैसे प्राप्त होता है? copy_to_user (usr_buf, drv_buf, count) copy_to_user (buf, drv_buf, count) होना चाहिए। –

+0

* "उपयोगकर्ता प्रोग्राम की प्रतिलिपि बनाने से पहले डेटा को ओवरराइट नहीं किया गया है, यह सुनिश्चित करने के लिए मैं किस तंत्र का उपयोग कर सकता हूं?" * - अनिवार्य रूप से चालक बफर ओवररन होने तक जितना हो सके उतना ही बफर कर सकता है। ए (स्थैतिक रूप से आवंटित) रिंग बफर (जैसा कि किसी उत्तर में प्रस्तावित किया गया है) केवल (रिंग) बफर के आकार के होने पर केवल ओवररन को स्थगित कर सकता है। एक अच्छी तरह से लिखित ड्राइवर ऐसी स्थिति का पता लगाने और रिपोर्ट करने में सक्षम होगा। गतिशील रूप से आवंटित बफर भी "धीमे" पाठक से निपटने के लिए अपर्याप्त हो सकते हैं। अब आपको यह सुनिश्चित करना होगा कि उपयोगकर्ता स्पेस कम से कम कुछ औसत दर के लिए पहुंचने वाले डेटा के साथ रह सकता है। – sawdust

उत्तर

2

हां, एक अंगूठी बफर काम करेगा।

आपको बस इंटरफ़ेस हैंडलर से बफर भरना होगा और आप इसे my_read कॉलबैक से पढ़ लेंगे।

वास्तव में एक अनुभवहीन है और वास्तव में वास्तव में अक्षम कार्यान्वयन (untested) हो सकता है:

static irqreturn_t irq_handler(int irq, void *dev_id) 
{ 
     struct my_dev *dev = dev_id; 

     buf[buf_wr] = read_device(dev); 
     buf_wr++; 

     if (buf_wr >= BUFSIZE) 
       buf_wr = 0; 

     wake_up(&wq); 
     return IRQ_HANDLED; 
} 

static ssize_t my_read(struct file *file, char __user *ubuf, 
          size_t sz, loff_t *ppos) 
{ 
     int n, ret; 

     ret = wait_event_interruptible(wq, 
           buf_wr != buf_rd); 
     if (ret) 
       return ret; 

     n = buf_wr - buf_rd; 
     if (n < 0) 
       n += BUFSIZE; 

     n = min(count, n); 
     ret = copy_to_user(ubuf, buf, n); 
     buf_rd += n; 

     if (buf_rd >= BUFSIZE) 
       buf_rd -= BUFSIZE; 

     if (ret) 
       return ret; 

     *ppos += n; 
     return 1; 
} 

तुम भी डीएमए या mmap या दोनों का उपयोग करने के लिए और अधिक कुशल कुछ पाने के लिए कर सकते हैं।

+0

जब दो से अधिक उपयोगकर्ता रिंग बफ तक पहुंच सकते हैं, तो इसे कुछ सिंक्रोनस आदिम द्वारा संरक्षित किया जाना चाहिए, जिसका अर्थ है इंटरप्ट हैंडलर-irq_handler में, सो सकता है? –

+0

उपयोगकर्ता स्पेस सिग्नल लिनक्स कर्नेल में बाधा के बराबर है हां आप रिंग बफर तंत्र का उपयोग कर सकते हैं। लेकिन आपको डेटा –

+0

डेटा की सुरक्षा के लिए कर्नेल सिंक्रनाइज़ेशन विधि का उपयोग करने की आवश्यकता है, आपको निश्चित रूप से उचित लॉकिंग का उपयोग करना होगा (यहां, एक म्यूटेक्स शायद पर्याप्त है)। जैसा कि कहा गया है, यह वास्तव में एक सरल कार्यान्वयन है, –

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