2009-08-03 30 views
18
#include <stdio.h> 

int main() { 
    while(!DONE) { 
    /* check for stuff */ 
    } 
    return 0; 
} 

Mẫu mã trên sử dụng 100% CPU cho đến khi DONE là đúng. Làm thế nào tôi có thể thực hiện một chương trình mà vòng và chỉ chấm dứt khi DONE, nhưng mà không sử dụng CPU 100%? Ngôn ngữ hiện đại sử dụng một cái gì đó như App.ProcessMessages hoặc một cái gì đó như thế để cung cấp cho hệ điều hành sự kiểm soát cho thời điểm này và sau đó quay trở lại vòng lặp.C Vòng lặp chính không có 100% cpu

Tôi mới tại C, rõ ràng là ... sử dụng GCC mới nhất, Linux và cửa sổ (một giải pháp di động sẽ là tuyệt vời!)

+8

Bạn nên sử dụng đối tượng đồng bộ hóa, một đối tượng mà bạn có thể đợi cho đến khi nó được báo hiệu, theo cách đó bạn sẽ không tiêu thụ CPU chút nào. –

+2

'DONE' là gì và điều gì sẽ khiến nó không khác? Có lẽ nó có ý nghĩa để tiếp tục xử lý cho đến khi 'kiểm tra các công cụ' đánh giá một cái gì đó mà đặt DONE là khác không? –

+0

Lasse V. Karlsen: Giải pháp của bạn có vẻ hợp lý (có thể nó có ý nghĩa rất nhiều, nhưng tôi không có kiến ​​thức đó). Bạn có thể vui lòng xây dựng? Tôi có nên điều tra chủ đề không? (ví dụ sẽ là tốt đẹp) Charles Bailey: XONG phải là một int (được thực hiện thay vì XONG) và nó sẽ được đặt thành 1 khi người dùng chọn thoát khỏi ứng dụng, chẳng hạn. Tôi xin lỗi nếu tôi không thể giải thích cho bản thân mình đủ tốt. – pwseo

Trả lời

16

Nó phụ thuộc vào những gì bạn muốn làm bên trong vòng lặp này.

Nếu bạn đang chờ đợi bên trong vòng lặp (ví dụ: nếu nhấn phím {do something} thì cơ chế của bạn sẽ lãng phí tài nguyên hệ thống không trả lại gì. Một bộ xử lý nhanh hơn sẽ chỉ tạo ra nhiều vòng không hoạt động hơn. chỉ cần ngủ, nhưng tốt hơn là một sự kiện kích hoạt một cái gì đó có ý nghĩa có thể được thực hiện.Ví dụ, một hoạt động tập tin (stdin cũng là một tập tin) sẽ là một cơ chế di động. cụ thể hơn, nó có thể được yêu cầu để nhảy vào các semaphores hoặc các tín hiệu mà thường phụ thuộc vào hệ điều hành.Một lớp trừu tượng có thể giải quyết vấn đề này

Nếu bạn đang làm một cái gì đó hữu ích (tức là xử lý nhiều dữ liệu), sau đó tải 100% CPU có nghĩa là bộ vi xử lý là chúng ta ed theo cách hiệu quả nhất. Bạn có thể dựa vào hệ điều hành để nhường chỗ cho các nhiệm vụ ưu tiên khác và có thể cao hơn.

Sử dụng chức năng như chế độ ngủ sẽ giảm mức sử dụng CPU, nhưng ứng dụng của bạn sẽ chậm hơn. Nó sẽ yêu cầu để có được một sự cân bằng giữa hiệu suất chấp nhận được và tải CPU. Tốc độ thực thi tối đa sẽ được xác định bởi tham số giấc ngủ của bạn và không còn bởi tốc độ CPU. Ngoài ra, nếu điện là một mối quan tâm (tức là thời gian sử dụng pin), thì điều này sẽ yêu cầu cpu để đánh thức (kết thúc thời gian ngủ) mà không có công việc phải làm; tức là một sự lãng phí tài nguyên hệ thống khác nhau.

+0

Tôi đoán tôi sẽ phải tìm hiểu các semaphores và tín hiệu sau đó Bất kỳ con trỏ cụ thể về điều đó? :) – pwseo

+2

Loại xử lý nào nằm trong vòng lặp chính? Tin nhắn, tín hiệu, semaphores có liên quan nhiều hơn đến hệ điều hành mà anh ấy nói ngôn ngữ cơ bản. Ví dụ: http://www.ibm.com/developerworks/eserver/library/es-win32linux-sem.html hiển thị cách các semaphores được xử lý trong các cửa sổ so với linux. Nếu bạn cần hỗ trợ cả hai, bạn có thể sử dụng POSIX (tùy chọn cho các cửa sổ, tức là trong Cygwin) hoặc đặt mã trong mô-đun phụ thuộc vào nền tảng mà bạn tạo cho mỗi hệ điều hành. – Adriaan

1

sử dụng

Sleep (int mili giây)

+3

Đối số cho giấc ngủ thực sự là một số giây, không phải là mili giây. –

+1

Tôi nghĩ rằng nó thực sự phụ thuộc vào hệ điều hành ... trong khi bạn đang đúng về tham số là giây dưới Unix/Linux/* BSD, tôi nghĩ rằng tôi nhớ nó được mili giây dưới Windows ... Đó là năm mặc dù, vì vậy tôi có thể sai ... – Nicolas

+5

sleep() mất số giây. usleep() (BSD và POSIX) mất micro giây. nanosleep() (POSIX quá) mất nano giây. – qrdl

3

gì chính xác bạn đang kiểm tra?

Nếu bạn đang kiểm tra thứ gì đó dễ bay hơi được thay đổi theo phần cứng hoặc quy trình khác, chỉ cần gọi sleep trong vòng lặp của bạn.

Nếu bạn đang chờ bộ mô tả tập tin hoặc bộ mô tả ổ cắm mạng, bạn sẽ muốn sử dụng select hoặc poll trong vòng lặp của bạn để đợi bộ mô tả có sẵn dữ liệu để sử dụng.

0

Sử dụng yield().

+0

Đây không phải là di động, vì nó được xác định bởi cả tiêu chuẩn C lẫn POSIX. –

+1

Điều đó sẽ không chỉ cung cấp cho các quy trình khác thêm thời gian, vẫn tiếp tục tất cả các quá trình khác không tiêu thụ? – liori

0

Nếu tôi đoán chính xác (tôi không biết về nó), tương đương với App.ProcessMessages đang thực hiện chặn IO. Và như tôi không biết bất kỳ việc thực hiện C trên hệ điều hành đa nhiệm sử dụng bỏ phiếu, bất kỳ tiêu chuẩn C IO nên được an toàn.

5

Hai tùy chọn của bạn sẽ là bỏ phiếu và một số loại thông báo sự kiện.

Việc bỏ phiếu sẽ dễ dàng nhất để lập trình - về cơ bản bạn có thể ngủ trong một thời gian ngắn mỗi khi vượt qua vòng lặp. Thao tác này sẽ giải phóng bộ xử lý cho các tác vụ khác. Nhược điểm là sẽ có một sự chậm trễ trong "kiểm tra cho công cụ" mã của bạn - vì vậy nếu bạn đang ngủ trong một giây, nó có thể lên đến một giây trước khi mã của bạn phát hiện tình trạng. Mã của bạn ở đây sẽ dễ dàng cổng.

Tùy chọn khác là đợi trên điều kiện POSIX, hoặc sự kiện Windows hoặc điều gì đó tương tự. Không chỉ mã này sẽ được thay đổi, nhưng sau đó "công cụ bạn đang kiểm tra" sẽ cần phải kích hoạt cờ để nói rằng nó được thực hiện. Đây sẽ là một mã ít cầm tay hơn, mặc dù có thể có các thư viện để trừu tượng hóa nền tảng. Nhưng bạn sẽ nhận được kết quả ngay lập tức cho sự kiện, và không có thời gian xử lý lãng phí kiểm tra những thứ không có ở đó.

+1

+1 để đề xuất sử dụng đồng bộ hóa POSIX. –

9

Bạn có nhiều lựa chọn:

  1. Sử dụng giấc ngủ() để buộc quá trình đình chỉ theo định kỳ và cho phép quá trình khác để sử dụng CPU
  2. Run ở mức ưu tiên thấp hơn - đó sẽ gây ra hệ điều hành để gán ít CPU thời gian
  3. Sử dụng một mutex hoặc đối tượng đồng bộ khác để phát hiện khi công việc có sẵn - đó sẽ tiếp tục quá trình này từ tốn bất kỳ thời gian CPU trừ khi nó thực sự đang làm việc
  4. Nếu bạn nhận được công việc nhanh hơn bạn có thể xử lý nó - bạn vẫn có thể cần có một số kiểu ngủ/mô hình ưu tiên để tránh hoàn toàn tiêu thụ CPU.

Tùy chọn # 2 có thể khó thực hiện trong nền tảng/hệ điều hành trung lập. Đặt cược tốt nhất của bạn là khởi chạy tiến trình và thay đổi ưu tiên của nó trong môi trường thời gian chạy.

0

Trên cửa sổ, bạn có thể sử dụng chế độ Ngủ (int mili giây), được xác định trên windows.h.

2

Nếu tôi hiểu đúng, bạn đã nói trong các nhận xét rằng DONE có thể được thay đổi từ các chủ đề khác. Nếu vậy, các biến điều kiện có ý nghĩa. Với pthreads, người ta sẽ làm:

Trong thread mà chờ đợi:

pthread_mutex_lock(&mutex); 
while (!DONE) { 
    pthread_cond_wait(&cond, &mutex); 
} 
pthread_mutex_unlock(&mutex); 

Trong bài khác, khi thực hiện là thay đổi:

pthread_mutex_lock(&mutex); 
DONE = 1; 
pthread_cond_signal(&cond); 
pthread_mutex_unlock(&mutex); 
+0

Bạn có thể mở khóa một chuỗi từ một chủ đề khác? – user457015

Các vấn đề liên quan