2012-06-29 11 views
9

Được rồi, vì vậy câu hỏi này không chính xác về quản lý chuỗi ... tốt, sắp xếp. Tôi đang tìm các giải pháp khác nhau cho cấu hình này. Tôi có một vài ý tưởng, nhưng tôi đang tìm kiếm bất kỳ giải pháp nào có thể đáp ứng được vấn đề. Và sẽ cân nhắc những ưu và khuyết điểm để thực hiện tốt nhất.Tôi cần phải thực hiện một cách để ngủ chủ đề này cho đến khi nó có tác dụng để làm

Đây là tình huống.

Tôi có một ứng dụng quản lý sẽ sinh ra một chuỗi. Chủ đề này sẽ liên tục chạy và xử lý giao tiếp nối tiếp với các bo mạch được kết nối với hệ thống qua USB. Ứng dụng quản lý tạo điều kiện giao tiếp giữa các ứng dụng khác đang chạy trên hệ thống và luồng này. Chủ đề cần phải thực sự thực hiện hai điều:

  1. Thăm dò bảng dữ liệu mẫu qua nối tiếp trên bộ định thời biến .. thường khoảng một lần một phút (bus nối tiếp chậm, baud là 4800. Tôi không thể kiểm soát điều này)
  2. Tạo điều kiện giao tiếp với ứng dụng của người quản lý. (tức là các ứng dụng khác sẽ yêu cầu dữ liệu mẫu, người quản lý chuyển tiếp yêu cầu tới chủ đề. chủ đề thực hiện thao tác và trả về dữ liệu)

Thiết kế ban đầu của tôi là một công việc đơn giản. Tôi sử dụng một hàng đợi và một mutex cho người quản lý để giao tiếp luồng. Vì vậy, logic của các chủ đề như sau:

  1. Khởi
  2. Trong khi chúng tôi chưa nhận được một lệnh tắt máy từ người quản lý
  3. Nếu hẹn giờ chúng tôi là lên, thăm dò ý kiến ​​hội đồng quản trị cho dữ liệu
  4. Nếu không, kiểm tra xem liệu chúng tôi có thông báo do người quản lý đăng lên hàng đợi hay không. nếu có, hãy xử lý nó

Vấn đề là tôi không xem xét sử dụng CPU. 99,9% thời gian luồng của tôi không xử lý được gì và chỉ cần nhấc điện lên. Tôi cần phải thực hiện một cách để ngủ thread này cho đến khi nó có công việc để làm. Vì vậy, một vài ý tưởng:

Sử dụng chọn() để chặn. Điều này có thể chặn dựa trên bộ hẹn giờ tôi cần sử dụng và tôi có thể thay đổi cài đặt nhắn tin hàng đợi thành tin nhắn . Vì vậy, thay vào đó, các chủ đề sẽ mở một ổ cắm khách hàng để quản lý và người quản lý sẽ vượt qua các thông điệp trên socket đến các chủ đề . Sau đó, chọn() sẽ ngủ cho đến khi có hoạt động trên fd hoặc bộ hẹn giờ của tôi đã hết.

Pro: Chính xác chức năng tôi cần.

Con: Ổ cắm không phải là một quá trình xử lý nặng để giao tiếp với một chuỗi nơi bạn đã chia sẻ bộ nhớ chưa?

Sử dụng hệ thống tín hiệu. (Một người nào đó am hiểu hơn trong Linux có thể lên đường ở đây với một ví dụ thực hiện ... Tôi không chắc chắn làm thế nào để làm điều đó.) Nhưng thread có thể ngủ trong thời gian của bộ đếm thời gian, và thức dậy để xử lý nếu tín hiệu đã được nhận từ người quản lý.

Pro: Duy trì thực hiện hiện nay sử dụng bộ nhớ chia sẻ

Côn: Không chắc làm thế nào để thực hiện. Có một chức năng như select() mà làm việc với các tín hiệu thay vì fds?

Tiềm năng đột biến. Tôi có thể chặn cho đến khi một người quản lý đăng lên mutex.

Pro: Vẫn còn chia sẻ bộ nhớ

Côn: có thể cần phải di chuyển chế biến đếm thời gian để quản lý và điều đó thực sự không phải là một lựa chọn vì nó có tính giờ khác và công việc quan trọng để thực hiện.

Vui lòng giới thiệu và cảm thấy tự do để phê bình. Tôi mở cửa cho bất kỳ lựa chọn hiệu quả nào. Xin lưu ý rằng mặc dù điều này đang chạy trên một hệ thống nhúng, do đó việc sử dụng tài nguyên là rất quan trọng.

+3

Tại sao không sử dụng biến có điều kiện khi bạn phải chờ một sự kiện? Chủ đề được đưa vào giấc ngủ cho đến khi biến được báo hiệu bởi một luồng khác. – Tudor

+0

Tôi hoàn toàn có thể, nhưng vấn đề là tôi không muốn được xử lý bất cứ điều gì. Tôi không muốn liên tục kiểm tra giá trị của biến số sẽ thay đổi mỗi phút một lần. Đó là rất nhiều chi phí. Tôi muốn các thread ngủ để nó cho thời gian CPU. – linsek

+1

Đảm bảo bạn tránh điều này: http://stackoverflow.com/questions/3886171/why-thread-sleep-is-so-cpu-intensive –

Trả lời

3

Hãy thử một cái gì đó như thế này, sử dụng Cột:

#include <stdio.h> 
#include <unistd.h> 
#include <pthread.h> 
#include <semaphore.h> 

static sem_t s_sem; 
static int iAlive = 1; 

void* thFunc(void *param) 
{ 
    printf("%s : ENTER \n", __FUNCTION__); 
    while(iAlive) 
    { 
     printf("%s : waiting \n", __FUNCTION__); 
     sem_wait(&s_sem); 

     printf("%s : got a signal - doing something \n", __FUNCTION__); 
     sleep(1); 
    } 

    printf("%s : EXIT \n", __FUNCTION__); 
    return 0; 
} 

int main() 
{ 
    pthread_t thread; 
    sem_init(&s_sem, 0, 0); 

    if(0 != pthread_create(&thread, NULL, thFunc, NULL)) 
    { 
     printf("%s : pthread_create FAILED \n", __FUNCTION__); 
     return -1; 
    } 

    while (getchar() != 'q') 
    { 
     printf("%s : sending signal \n", __FUNCTION__); 
     sem_post(&s_sem); 
    } 

    iAlive = 0; 
    sem_post(&s_sem); 
    pthread_join(thread, NULL); 
    sem_destroy(&s_sem); 

    return 0; 
} 

Bạn có thể thay sem_wait với sem_timedwait nếu bạn cần một thời gian chờ.

3

Yêu cầu mỗi chuỗi chờ trên hàng đợi người tiêu dùng-nhà sản xuất đầu vào với thời gian chờ. Nếu hàng chờ đợi, hãy thăm dò liên kết nối tiếp, nếu không thì xử lý lệnh nhận được trên hàng đợi. Để tạo thành một hàng đợi phù hợp từ đầu, bạn cần một hàng đợi thực, (mà bạn đã có), một mutex để bảo vệ các con trỏ/chỉ mục, (mà bạn đã có), và một semaphore, được khởi tạo là 0, chờ đợi (timeout) chức năng. Để gửi yêu cầu, hãy khóa mutex, đẩy yêu cầu, mở khóa mutex, báo hiệu semaphore. Trong chủ đề, chờ đợi trên semaphore, nếu chờ đợi trở lại mà không có thời gian chờ, khóa mutex, pop yêu cầu, (cho sẽ luôn có một), mở khóa mutex và xử lý các yêu cầu nhận được. Nếu chờ đợi sema trả về với thời gian chờ, hãy thăm dò liên kết nối tiếp. Khi hoàn thành, lặp lại để chờ đợi trên semaphore một lần nữa.

Để thay đổi thời gian chờ, gửi thông báo chuỗi bằng lệnh 'EchangeWaitInterval', (nói :) và khoảng thời gian chờ mới để sử dụng cho lần chờ tiếp theo.

4

Chuyển sang hàng đợi tin nhắn POSIX thay vì hàng đợi của riêng bạn. mq_timedreceive sẽ trả về nếu người quản lý đăng một yêu cầu. Nếu nó hết thời gian, bạn phải thực hiện kiểm tra bộ đếm thời gian. Việc đồng bộ hóa và chặn đã được đóng gói.

+0

Yup, điều đó nên làm. –

+0

hơi quá nặng, các phép ẩn dụ đơn giản hơn một chút. –

5

Công cụ cổ điển để xử lý các tình huống như vậy là các ẩn dụ chứ không phải các biến thể hoặc biến điều kiện. Hãy suy nghĩ của họ như là thẻ thông qua từ người quản lý đến chủ đề.

Chủ đề có thể sử dụng sem_timedwait để đảm bảo thức dậy một lần trong một thời gian để kiểm tra dữ liệu.

Cẩn thận để nắm bắt các lỗi trả về của sem_ hoạt động tốt, chúng có thể bị gián đoạn. Vì vậy, bạn có thể có nhiều hơn một chút thức dậy hơn bạn nghĩ.

+0

Một vài câu trả lời semaphore ở đây vì vậy sẽ chỉ trả lời tất cả chúng ở đây. Sẽ sử dụng một semaphore như một bộ đếm thời gian để thức dậy và kiểm tra dữ liệu hiệu quả hơn là chặn với select() và nhận dữ liệu trên một socket? Một mặt, tôi đang sử dụng bộ nhớ chia sẻ thay vì recv(), nhưng mặt khác, nếu tôi không bao giờ nhận được yêu cầu từ một ứng dụng khác. Tôi đang xử lý không có lý do. – linsek

+0

Khi bạn mô tả vấn đề của bạn, thực tế là thread của bạn không ngủ thực sự là đáng kể. Điều này có nghĩa là nếu bạn xoay nó xung quanh, luồng của bạn không hoạt động nhiều so với điều đó. Vì vậy, nếu bạn nắm vững vấn đề "ngủ" này, giải pháp bạn thực hiện sẽ không có tác động nhiều đến công việc tổng thể (chu kỳ CPU) được sử dụng bởi luồng. Sự khác biệt là sau đó trong (1) thuận tiện, những gì được lập trình và duy trì độ trễ dễ nhất (2). Đối với cả hai tôi nghĩ rằng semaphores giành chiến thắng. –

+0

Chờ đợi semaphore đang chặn. Nếu wait() chưa hết thời gian và semaphore chưa được báo hiệu và số đếm nội bộ của nó bằng 0, không có CPU nào được sử dụng cả. Việc chờ đợi sem (timeout) sẽ không chỉ trở lại cho đến khi một điều kiện hoặc khác được hài lòng. Nếu thời gian chờ đợi, các thred sẽ chạy một lần. Nếu semaphore được báo hiệu 15 lần bởi người quản lý xếp hàng các tin nhắn, chủ đề sau đó sẽ chạy 15 lần và xử lý tất cả 15 và không còn nữa. –

0

Cách tiếp cận pthreads cổ điển với điều này sẽ là để chặn chuỗi của bạn trong pthread_cond_wait() cho đến khi chuỗi người quản lý đặt một thông báo trong hàng đợi và báo hiệu biến điều kiện. Trong trường hợp này, để đánh thức kịp thời để thăm dò ý kiến ​​các thiết bị nối tiếp, hãy sử dụng pthread_cond_timedwait() để thay thế.