2010-05-27 11 views
39

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

int filedesc = open("dev/ttyS0", O_RDWR); 

read(filedesc, buff, len); 

संपादित करें:

मैं लिनक्स ओएस उपयोग कर रहा हूँ। चुनिंदा फ़ंक्शन कॉल का उपयोग करके कैसे कार्यान्वित करें?

+3

देखें http://linux.die.net/man/2/select – sizzzzlerz

उत्तर

64

चयन करें() 5 पैरामीटर लेता है, पहले उच्चतम फ़ाइल डिस्क्रिप्टर + 1, फिर पढ़ने के लिए एक fd_set, लिखने के लिए एक और अपवादों के लिए एक। अंतिम पैरामीटर एक स्ट्रक्चर टाइमवल है, जो टाइमआउट के लिए उपयोग किया जाता है। यह +1 पर त्रुटि, 0 समय पर सेट या सेट सेट में फ़ाइल डिस्क्रिप्टर की संख्या।

#include <stdio.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <sys/select.h> 

int main(void) 
{ 
    fd_set set; 
    struct timeval timeout; 
    int rv; 
    char buff[100]; 
    int len = 100; 
    int filedesc = open("dev/ttyS0", O_RDWR); 

    FD_ZERO(&set); /* clear the set */ 
    FD_SET(filedesc, &set); /* add our file descriptor to the set */ 

    timeout.tv_sec = 0; 
    timeout.tv_usec = 10000; 

    rv = select(filedesc + 1, &set, NULL, NULL, &timeout); 
    if(rv == -1) 
    perror("select"); /* an error accured */ 
    else if(rv == 0) 
    printf("timeout"); /* a timeout occured */ 
    else 
    read(filedesc, buff, len); /* there was data to read */ 
} 
+2

यह समाधान पर्याप्त नहीं है क्योंकि अगर हम 5 बाइट्स की प्रतीक्षा कर रहे हैं लेकिन समय में केवल 1 प्राप्त किया गया है तो चयन ठीक रहेगा और फिर हम हमेशा पढ़ने के लिए ब्लॉक करेंगे। – Roskoto

+7

नहीं, यह नहीं होगा। यदि केवल एक बाइट उपलब्ध था और आप 5 पढ़ने की कोशिश करते हैं, तो पढ़ें() ब्लॉक नहीं होगा, यह 1 लौटाएगा (बाइट्स पढ़ने की संख्या)। पढ़े गए मैन-पेज से: "यह त्रुटि नहीं है यदि यह संख्या अनुरोधित बाइट्स की संख्या से छोटी है; यह उदाहरण के लिए हो सकता है क्योंकि कम बाइट वास्तव में उपलब्ध हैं (शायद क्योंकि हम अंत- ऑफ-फाइल, या क्योंकि हम पाइप से या टर्मिनल से पढ़ रहे हैं), या क्योंकि पढ़ा गया था() सिग्नल द्वारा बाधित था। " – Puppe

+0

और समय-समय पर "चयन" कैसे करें, दूसरी बार तत्काल वापस आ जाएगा। मैं जानना चाहता हूं क्यो ? – kangear

7

यदि आप सॉकेट को गैर-अवरुद्ध मोड में संचालित करते हैं, तो पढ़ने के लिए प्रत्येक कॉल केवल वर्तमान में उपलब्ध डेटा (यदि कोई हो) पढ़ेगी। तो यह प्रभावी रूप से तत्काल टाइमआउट के बराबर है।

आप गैर अवरुद्ध मोड इस तरह एक समारोह के साथ एक सॉकेट पर सेट कर सकते हैं: (read आदमी पृष्ठ देखें गैर अवरुद्ध सॉकेट से पढ़ने के बारे में अधिक जानकारी के लिए)

int setnonblock(int sock) { 
    int flags; 
    flags = fcntl(sock, F_GETFL, 0); 
    if (-1 == flags) 
     return -1; 
    return fcntl(sock, F_SETFL, flags | O_NONBLOCK); 
} 

4

आपके पास ओएस क्या नहीं है लेकिन अगर आप लिनक्स के तहत चल रहे हैं, तो आप चुनिंदा कॉल का उपयोग कर सकते हैं। फ़ाइल डिस्क्रिप्टर पर कुछ पढ़ने के लिए यह लौटाता है या आप इसे सेट अप कर सकते हैं ताकि पढ़ने के लिए कुछ भी न हो। रिटर्न कोड इंगित करता है कि कौन सा है।

35

एक सीरियल पोर्ट (टर्मिनल) आप tcsetattr() उपयोग कर सकते हैं पढ़ने टाइमआउट के साथ गैर-प्रामाणिक मोड में फ़ाइल वर्णनकर्ता डाल करने के लिए, के विशिष्ट मामले के लिए select() के लिए एक विकल्प के रूप में।

इस सेट नहीं ICANON झंडा करने के लिए, और VTIME नियंत्रण चरित्र सेट:

struct termios termios; 

tcgetattr(filedesc, &termios); 
termios.c_lflag &= ~ICANON; /* Set non-canonical mode */ 
termios.c_cc[VTIME] = 100; /* Set timeout of 10.0 seconds */ 
tcsetattr(filedesc, TCSANOW, &termios); 

नोट VTIME एक दूसरे का दसवां में मापा जाता है, और उस प्रकार यह के लिए इस्तेमाल आम तौर पर एक unsigned char, जिसका अर्थ है कि अधिकतम टाइमआउट 25.5 सेकेंड है।

+3

मुझे शायद ही कभी किसी को टर्मिनल रीड टाइम आउट का उल्लेख दिखाई देता है। – nategoose

+5

मेरे मामले में मुझे वीएमआईएन को 0: 'termios.c_cc [VMIN] = 0' पर सेट करना पड़ा। –

+0

मान लीजिए कि हमारे पास दो डिवाइस TxDev और RxDev हैं जो UART के माध्यम से टी = टी 1 पर संचार करते हैं, TxDev डेटा भेजना शुरू करता है, इस समय RxDev पढ़ा गया निर्देश तक नहीं पहुंचता है फिर भी TxDev द्वारा भेजे गए पहले बाइट्स खो जाते हैं ?, या RxDev एक बफर है जहां यह प्राप्त डेटा संग्रहीत करता है भी पढ़ा जाता है? – fedi

-2

लिनक्स दो प्रकार के डिवाइस पर विचार करता है। "धीमा" (जैसे नेटवर्क) और "तेज़" एक (उदाहरण डिस्क)। गैर अवरोधन मोड "धीमी" डिवाइस के लिए है, न कि "तेज"। ब्लॉक को "तेज़" माना जाता है, इसलिए चयन/चुनाव हमेशा बताएं कि वे I/O के लिए तैयार हैं। कुछ फ्लैश डिवाइस के लिए, यह एक झूठ है और मैंने कुछ I/O कॉल देखा है जो कुछ बाइट्स के लिए कई सेकंड का उपयोग करते हैं, भले ही चयन/सर्वेक्षण बताता है कि डिवाइस तैयार है। यह कहा गया है कि धीमी डिवाइस के लिए भी, पढ़ने में देरी पर कोई मजबूत वारंटी नहीं है; यदि आप एक बड़ा बफर प्रदान करते हैं और डेटा उपलब्ध है (आपने इसका चयन करने के लिए चयन या मतदान का उपयोग किया है), तो कॉल स्वयं एक महत्वपूर्ण मात्रा (नेटवर्क पर एमएस के सौ) का उपयोग कर सकते हैं।

+4

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

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