2015-07-30 14 views
5

संपादित करें: I सोच मैंने समस्या हल की। जैसे ही मैं कल फिर से काम पर हूं, मैं अपना उत्तर/समाधान जोड़ूंगा।सी - लिनक्स कर्नेल: बंद करने के लिए दो kthreads फ्रीज मशीन


मैं लिनक्स कर्नेल 3.16.x के लिए कर्नेल मॉड्यूल पर काम कर रहा हूं। मेरा मॉड्यूल ईथरनेट फ्रेम प्राप्त करने और भेजने के लिए माना जाता है, इसलिए मैंने दो धागे बनाए। भाग प्राप्त करने के लिए एक, भाग भाग के लिए एक। यह ठीक काम कर रहा है।

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

TX थ्रेड: सेमाफोर tx_sem कोड के दूसरे हिस्से में up'ed है

यहाँ मेरी दो धागे हैं।

static int tx_task(void *par) 
{ 
    device->tx_task_running = 1; 

    allow_signal(SIGTERM); 
    while (!signal_pending(current) && device->tx_task_running) { 
     /* wait until there is something to send */ 
     down_interruptible(&device->tx_sem); 

     if (signal_pending(current)) { 
      PRINTD("device_TX_task(): Received kill signal\n"); 
      break; 
     } 

     /* check if device is still initialized before continuing*/ 
     if (!device->init_flag) { 
      break; 
     } 
    } 
    device->tx_task_running = 0; 
    return DEVICE_RET_OK; 
} 

RX थ्रेड

static int device_rx_task(void *par) 
{ 
    device->rx_task_running = 1; 

    /* task loop */ 
    allow_signal(SIGTERM); 
    while (!signal_pending(current) && device->rx_task_running) { 
     rxlen = kernel_recvmsg(device->sock, &msg, 
      (struct kvec *)&iov, 1, DEVICE_PAY_SIZE, 0); 

     if (signal_pending(current)) { 
      PRINTD("device_rx_task(): Received kill signal\n"); 
      break; 
     } 

     if(rxlen < 0) { 
      PRINTD("device_RX_task(): Got error when receiving\n"); 
      break; 
     } 

     /* check if device is still initialized before continuing*/ 
     if (!device->init_flag) { 
      break; 
     } 
    } 
    device->rx_task_running = 0; 
    return DEVICE_RET_OK; 
} 

ये लोग चलाते हैं जब तक मैं अपने डिवाइस बंद करने के लिए प्रयास करें। कर्नेल मॉड्यूल को बंद करते समय, यह फ़ंक्शन कॉल हो जाता है और यह तब होता है जब यह क्रैश हो जाता है। उदाहरण के लिए, यदि मैं "send_sig" फ़ंक्शंस को टिप्पणी करता हूं, तो यह क्रैश नहीं होता है। यह भी दुर्घटनाओं जब मैं मैन्युअल रूप से धागे को मारने की कोशिश:

int Device_DevTerm(int dev) 
{ 
    device->init_flag = 0; 

    send_sig(SIGTERM, device->rx_thread, 0); 
    send_sig(SIGTERM, device->tx_thread, 0); 
    device->rx_task_running = 0; 
    device->tx_task_running = 0; 

    return DEVICE_RET_OK; 
} 

मैं googled और आदेश समस्या खोजने के लिए एक लंबे समय के लिए खोज की है, लेकिन अब तक मैं सफल नहीं था। चूंकि मैंने इस मुद्दे के लिए बहुत समय पहले ही बिताया है, इसलिए मैंने आपको लोगों से पूछने का फैसला किया।

मैं यहाँ क्या गलत कर रहा हूं?

पेज। मुझे नहीं लगता कि मैंने कभी यहां पोस्ट किया है, मैंने बस बहुत कुछ पढ़ा है। मुझे उम्मीद है कि मेरा प्रश्न स्पष्ट और संक्षेप में पर्याप्त है। शायद ऩही।

+1

यदि यह स्टैक ट्रेस पोस्ट को क्रैश कर रहा है। यदि आप लटका चाहते हैं, तो लटका कार्य खोजने के लिए SysRq का उपयोग करें। – stark

+0

दुर्भाग्यवश ऐसा करने में असमर्थ लगता है। जब मैं/var/log/syslog में देखता हूं/हैंग के बारे में कुछ भी नहीं है। मुझे लगता है कि किसी भी आउटपुट होने से पहले यह जम गया। जब मैं SysRq (जिसे मैं पहले नहीं जानता था) कोशिश करता हूं कुछ भी नहीं होता है, यह जमे हुए रहता है। शायद यह तथ्य कि यह एक वर्चुअल मशीन है, मदद नहीं करता है, मुझे यकीन नहीं है। मैं किसी भी उपयोगी जानकारी को इकट्ठा करने की कोशिश करना जारी रखूंगा, लेकिन अभी तक मैं सक्षम नहीं हूं। –

उत्तर

0

तो ऐसा लगता है जैसे मुझे मेरी समस्या मिली। इस के साथ ऐसा नहीं होता

struct sockaddr_in client[3]; 

MEM_SET(&client[0], 0x00, 3 *sizeof(struct sockaddr_in)); 

/* setup receive parameter */ 
msg.msg_name = &client[1]; 
msg.msg_namelen = sizeof(struct sockaddr_in); 
msg.msg_control = NULL; 
msg.msg_controllen = 0; 
msg.msg_iov = &iov; 
msg.msg_iovlen = 1; 

:

struct sockaddr_in client; 

MEM_SET(&client, 0x00, sizeof(struct sockaddr_in)); 

/* setup receive parameter */ 
msg.msg_name = &client; 
msg.msg_namelen = sizeof(struct sockaddr_in); 
msg.msg_control = NULL; 
msg.msg_controllen = 0; 
msg.msg_iov = &iov; 
msg.msg_iovlen = 1; 

अब मैं करने के लिए दिनचर्या बदल दिया है:

जब kernel_recvmsg() फ़ंक्शन के लिए msghdr की स्थापना, मैं इस तरह यह करने के लिए इस्तेमाल किया अब दुर्घटनाग्रस्त तब मैं हमारे कोड बेस में निम्नलिखित टिप्पणी पाया:

/* 
* NOTE: 
* use three times the size of struct sockaddr_in as workaround 
* for a possible kernel bug which has been seen on a Ubuntu 64bit 
* system 
* after the call of kernel_recvmsg 2 bytes behind the structure 
* client had been corrupted on the stack 
*/ 

मैं कैसे सच है कि और चाहे या नहीं यह मेरी पूरी समस्या शामिल हैं यकीन नहीं है, लेकिन यह इसे ठीक कर रहा है।

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