2012-12-28 27 views
10

Tôi đã viết một chương trình trong C chờ một sự kiện và sau đó chạy lệnh hệ thống bên ngoài theo chức năng system().nhà sản xuất nhanh/người tiêu dùng chậm trong C

while(true){ 
    wait_for_event(); 
    system("cmd"); 
} 

Tôi có một vấn đề seriuos về vấn đề này, The cmd là một lệnh nặng và phải mất vài giây để hoàn thành, ứng dụng của tôi bỏ lỡ một số sự kiện trong khoảng thời gian này.

Vì vậy, tôi quyết định chuyển system chức năng, mà là rất nặng nề, để một chương trình khác, Vì vậy, tôi đã thay đổi chương trình của tôi như sau:

while(true){ 
    wait_for_event(); 
    write_to_fifo("cmd"); 
} 

và viết một chương trình khác:

while(true){ 
    system(read_from_pipe()); 
} 

nhưng nó không giúp được gì, bởi vì nếu nhà sản xuất (chương trình 1) viết nhanh hơn người tiêu dùng (chương trình thứ 2), thì người tiêu dùng sẽ bỏ sót một số dữ liệu!

Có cách nào để xử lý sự cố này không?

+4

Sử dụng chuỗi để nắm bắt các sự kiện, thêm chúng vào hàng đợi và yêu cầu người tiêu dùng của bạn kéo từ hàng đợi đó. – Falmarri

+0

Có thể sử dụng nhiều chủ đề để giảm gánh nặng cho người tiêu dùng trong khi rời khỏi nhà sản xuất đơn luồng không? Cấp, đó là một trận thua, nhưng nó có thể là đủ để giúp bạn tiết kiệm được yêu cầu của bạn. Bạn cũng nên xem xét một kho dữ liệu nếu nó vẫn trở nên quá nhiều cho các chủ đề phụ. – pickypg

+0

Làm cách nào để bạn thiết lập đường ống?Tất nhiên, nếu bạn liên tục nhận được nhiều dữ liệu hơn bạn có thể xử lý, một cái gì đó sẽ "cho". Nhưng hoàn toàn có thể sử dụng một đường ống để xử lý một lượng lớn dữ liệu từ từ. Nếu không, nó sẽ không hoạt động để làm 'mèo myprog.c | gcc -o myprog' - và nó - gcc là khá chậm ở lần, mèo sẽ đẩy nhanh như nó có thể vào đường ống. –

Trả lời

8

Bạn nên trả lại mã về dạng ban đầu — tức là một chương trình gọi một chương trình thứ hai — ngoại trừ việc bạn thay thế cuộc gọi system(3) bằng cuộc gọi popen(3). Giờ đây, chương trình gọi điện có thể xen kẽ các cuộc gọi để kiểm tra sự kiện bằng các dòng đọc từ chương trình bên ngoài.

Cơ chế ống Unix đảm bảo rằng người tiêu dùng chậm sẽ khiến nhà sản xuất nhanh phải chờ trong khi viết khi ống đầy.

Bạn cũng có thể muốn nhìn vào fileno(3) chức năng, kết hợp với select(2) hay poll(2) để làm cho việc đọc từ không đồng bộ chương trình bên ngoài, do đó nó có thể không bao giờ chặn các chương trình gọi điện thoại.

+0

Cảm ơn bạn đã phản hồi nhanh chóng. Tôi không quen thuộc với lập trình C dưới Linux, bạn vui lòng cung cấp cho mã mẫu. Cảm ơn – Maryam

+0

WoW! Nó hoạt động như một say mê! Cảm ơn – Maryam

+0

Bạn thực sự cần có một trong những cuốn sách về chủ đề này. Học nó từng mảnh có điểm của nó, nhưng có một gestalt bạn cần phải nhận, và điều đó chỉ xảy ra khi bạn học được rất nhiều trong một thời gian ngắn. Tôi khuyên bạn nên * Lập trình nâng cao trong môi trường Unix * 2/e bởi W. Richard Stevens. Có những cuốn sách khác. Không được tắt theo tuổi của cuốn sách này. Ngay cả ấn bản đầu tiên vẫn còn 95% hữu ích cho lập trình Linux hiện đại. Các API hạt nhân và thư viện chuẩn C chỉ đơn giản là không thay đổi nhiều trong thời gian đó. –

2

Nếu tất cả những gì bạn cần là số lượng sự kiện, bạn có thể có bộ đếm chung. Để tránh điều kiện chủng tộc, bạn có thể cần phải sử dụng semaphore thay thế. Tất nhiên bạn sẽ cần phải có hai chủ đề.

Vì sự kiện của bạn có chứa quan trọng, nên có thể sử dụng danh sách (hoặc mảng có đủ số lượng vị trí) để lưu trữ dữ liệu đến. Bạn có thể sử dụng một mutex để bảo vệ danh sách này.

+0

Không, sự kiện có một số dữ liệu quan trọng và chúng cần được xử lý và lưu trữ ở nơi khác. – Maryam

2

Bạn có thể bắt đầu chương trình bên ngoài của bạn một cách rõ ràng, sử dụng fork(2), execve(2), waitpid(2) và có lẽ pipe(2), dup2(2) và khác syscalls.

Có thể bạn cần một vòng lặp sự kiện. Bạn có thể sử dụng syscall poll(2) (hoặc có thể là thư viện vòng lặp sự kiện như libev, sử dụng poll).

Tôi đặc biệt khuyên bạn nên dành thời gian để đọc số advanced linux programming book tốt trước khi mã hóa.

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