2013-11-02 10 views
5

Tôi đang viết chương trình giao tiếp mạng bằng cách sử dụng các ổ cắm không chặn (C/C++) và select. Chương trình khá lớn, vì vậy tôi không thể tải lên mã nguồn. Trong một phiên thử nghiệm rất tích cực, tôi sử dụng mã thử nghiệm để mở và đóng cả TCP và UDP thường xuyên. Nó luôn luôn kết thúc mà một đầu không đáp ứng và có sử dụng CPU trên 98 hoặc 99%. Sau đó, tôi sử dụng gdb để đính kèm. "bt" hiển thị thông tin sau:Vấn đề select() sử dụng quá nhiều nguồn CPU là gì?

0x00007f1b71b59ac3 in __select_nocancel() at ../sysdeps/unix/syscall-template.S:82 
82 ../sysdeps/unix/syscall-template.S: No such file or directory. 
    in ../sysdeps/unix/syscall-template.S 

Loại lỗi này có thể là gì?

$ uname -a 
Linux kiosk2 2.6.32-34-generiC#77-Ubuntu SMP Tue Sep 13 19:39:17 UTC 2011 x86_64 GNU/Linux 
+0

Vì vậy, vấn đề là gì? – Tshepang

Trả lời

26

Đó là không thể nói mà không nhìn vào mã này, nhưng thường khi một vòng lặp chọn dựa trên bắt đầu quay với ~ 100% sử dụng CPU, đó là vì một hoặc nhiều ổ cắm bạn nói với select() xem là ready- cho đọc (và/hoặc sẵn sàng để viết) để select() trả về ngay lập tức thay vì chặn ... nhưng sau đó mã bỏ qua để thực sự recv() (hoặc send()) bất kỳ dữ liệu nào trên ổ cắm đó. Sau khi không đọc/ghi bất cứ điều gì, vòng lặp sự kiện của bạn sẽ cố gắng quay trở lại trạng thái ngủ bằng cách gọi lại select(), nhưng tất nhiên dữ liệu của socket (hoặc vùng đệm, trong trường hợp sẵn sàng ghi) vẫn đang chờ xử lý , vì vậy select() lợi nhuận ngay lập tức một lần nữa, các mã lỗi bỏ qua việc làm đọc (hoặc write()) một lần nữa, và xung quanh và xung quanh chúng tôi đi ở tốc độ tối đa :)

một khả năng khác sẽ được rằng bạn đang đi trong một giá trị thời gian chờ để select() đó là số không hoặc gần bằng không, làm cho select() trở lại rất nhanh ngay cả khi không có ổ cắm sẵn sàng cho bất cứ điều gì ... thường xảy ra khi mọi người quên khởi tạo lại cấu trúc timeval trước mỗi cuộc gọi đến select(). Bạn cần phải khởi tạo lại cấu trúc timeval mỗi lần bởi vì một số triển khai của select() sẽ sửa đổi nó trước khi trở về.

Đề xuất của tôi là đặt một số printf (hoặc yêu thích tương đương) ngay trước và ngay sau khi bạn gọi tới select() và xem đầu ra đó khi bạn tạo lại lỗi. Điều đó sẽ cho bạn biết liệu việc quay số có xảy ra bên trong một cuộc gọi duy nhất đến select() hay nếu điều gì đó đang gây ra select() để quay lại ngay lập tức.

+3

+1 một trong những câu trả lời hay nhất về SO mà tôi đã thấy khi không có mã nguồn trong câu hỏi –

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