2010-12-20 11 views
11

मैं किसी फ़ाइल प्रक्रियाकर्ता को किसी अन्य प्रक्रिया में स्थानांतरित करने के लिए एक यूनिक्स डोमेन सॉकेट का उपयोग कर रहा हूं। यह ठीक काम करता है, लेकिन जब मैं पहली बार यह देखने का प्रयास करता हूं कि सॉकेट चुनिंदा() का उपयोग करके लिखने योग्य है या नहीं, sendmsg() कॉल खराब फ़ाइल डिस्क्रिप्टर त्रुटि के साथ विफल रहता है।यूनिक्स डोमेन सॉकेट पर फ़ाइल डिस्क्रिप्टर भेजना, और चुनें()

प्रेषण() फ़ंक्शन चुनिंदा() के साथ संयोजन में ठीक काम करता है अगर मैं msghdr संरचना में फ़ाइल डिस्क्रिप्टर जानकारी नहीं जोड़ता, तो संघर्ष चुनिंदा() और फ़ाइल वर्णनकर्ताओं को स्थानांतरित करने के बीच लगता है।

मुझे चुनिंदा(), recvmsg(), या किसी अन्य के लिए मैन पेजों में इस पर कोई जानकारी नहीं मिली। चूंकि इसे एक सर्वर बनने की आवश्यकता है जो कई प्रक्रियाओं में फाइल डिस्क्रिप्टर को हाथ से बाहर रखता है, फिर भी मैं चुनिंदा() का उपयोग करने में सक्षम होना चाहता हूं।

क्या यह काम करने के लिए मैं कुछ भी कर सकता हूं, या क्या कोई वैकल्पिक समाधानों के बारे में जानता है?

प्लेटफार्म उबंटू 10.4 है।



struct cmsghdr_fd : public cmsghdr 
{ 
    int fd; 
}; 

int sendfd(int sock, int fd) 
{ 
    struct msghdr hdr; 
    struct iovec data; 
    struct cmsghdr_fd msgdata; 

    char dummy = '*'; 
    data.iov_base = &dummy; 
    data.iov_len = sizeof(dummy); 

    hdr.msg_name = NULL; 
    hdr.msg_namelen = 0; 
    hdr.msg_iov = &data; 
    hdr.msg_iovlen = 1; 
    hdr.msg_flags = 0; 

    hdr.msg_control = &msgdata; 
    hdr.msg_controllen = sizeof(msgdata); 

    struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr); 
    cmsg->cmsg_len = hdr.msg_controllen; 
    cmsg->cmsg_level = SOL_SOCKET; 
    cmsg->cmsg_type = SCM_RIGHTS; 

    *(int*)CMSG_DATA(cmsg) = fd; 

    int n = sendmsg(sock, &hdr, 0); 

    if(n == -1) 
    printf("sendmsg() failed: %s (socket fd = %d)\n", strerror(errno), sock); 

    return n; 
} 

फिर, यह काम करता है, के रूप में मैं चयन कॉल नहीं करते() पहले चाहे सॉकेट लेखन के लिए तैयार है की जाँच करने के रूप में लंबे समय:

इस कोड है कि संरचनाओं initializes है।

+0

क्या आप अपना कोड शामिल कर सकते हैं जो 'msghdr' और' cmsghdr' को पॉप्युलेट करता है? –

+0

मैं यह सत्यापित करता हूं कि आपके आस-पास का कोड msghdr की लंबाई (या डेटा स्वयं) को दूषित नहीं कर रहा है, क्योंकि कर्नेल के हैंडलिंग के बहुत कम पढ़ने से, मुझे लगता है कि यह संभावित समस्या – Hasturkun

+0

होगी जो मैंने कोड को पॉप्युलेट किया प्रश्न के लिए संरचनाएं। – svdree

उत्तर

10

मैंने this page पर sendfd कोड की कोशिश की, जिसे nos द्वारा प्रदान किया गया था, और भले ही यह केवल थोड़ा अलग है, यह तब भी काम करता है जब मैं इसे चयन() के साथ संयोजन में उपयोग करता हूं। यह कोड अब जैसा दिखता है:



    int sendfd(int sock, int fd) 
    { 
     struct msghdr hdr; 
     struct iovec data; 

     char cmsgbuf[CMSG_SPACE(sizeof(int))]; 

     char dummy = '*'; 
     data.iov_base = &dummy; 
     data.iov_len = sizeof(dummy); 

     memset(&hdr, 0, sizeof(hdr)); 
     hdr.msg_name = NULL; 
     hdr.msg_namelen = 0; 
     hdr.msg_iov = &data; 
     hdr.msg_iovlen = 1; 
     hdr.msg_flags = 0; 

     hdr.msg_control = cmsgbuf; 
     hdr.msg_controllen = CMSG_LEN(sizeof(int)); 

     struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr); 
     cmsg->cmsg_len = CMSG_LEN(sizeof(int)); 
     cmsg->cmsg_level = SOL_SOCKET; 
     cmsg->cmsg_type = SCM_RIGHTS; 

     *(int*)CMSG_DATA(cmsg) = fd; 

     int n = sendmsg(sock, &hdr, 0); 

     if(n == -1) 
     printf("sendmsg() failed: %s (socket fd = %d)\n", strerror(errno), sock); 

     return n; 
     } 

+0

अब कभी भी 'select' का उपयोग न करें। मैंने ओपी पर अपनी टिप्पणी में कारण दिए। 'पोल' सिस्टम कॉल (जो बीएसडी को पोर्टेबल है) या 'एपोल' सिस्टम' का प्रयोग करें। – Omnifarious

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