[英]How can I keep reading from a named pipe without 100% CPU usage?
最近,我一直在為我正在從事的一個大學項目使用命名管道。 我需要制作一個充當“服務器”的程序 - 它不斷地從命名的 pipe 讀取並執行通過所述 pipe 給它的任何命令。 我已經設法做到了,但有一個問題:100% 的 CPU 使用率。 顯然這是一個問題,它會導致我的教授的成績降低,所以我想減少這種情況。
編輯:我忘了提到從 pipe 讀取消息並執行它后,服務器必須繼續運行等待另一條消息。 服務器程序在任何時候都不應終止(發送 SIGINT 或類似信號時除外)。 期望的行為是它永遠不會離開循環,而只是繼續閱讀和執行 pipe 發送的消息。
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
int main () {
if (mkfifo("fifo", 0600) == -1) {
perror("Error on fifo");
return -1;
}
char buffer[1024];
int bytesWritten = 0;
int fifo = open("fifo", O_RDONLY);
while(1) {
bytesWritten = read(fifo, buffer, 1024);
if (bytesWritten > 0)
write(1, buffer, bytesWritten);
}
return 0;
}
僅在這個特定示例中,我並沒有在某些功能上處理錯誤,在我處理所有這些的實際項目中。 這段代碼只是打印出通過 pipe 傳遞給它的任何命令。
這是一個小程序,我通過 pipe 發送一些東西:
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
int main () {
int fifo = open("fifo", O_WRONLY);
write(fifo, "This is a test\n", strlen("This is a test\n"));
close(fifo);
return 0;
}
除了 CPU 使用問題外,這工作正常。 我想到的一件事是在 while 開始時使用pause()
,並每秒停止一次此暫停。
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
void alarm_handler(int signum) {
alarm(1);
}
int main () {
if (mkfifo("fifo", 0600) == -1) {
perror("Error on fifo");
return -1;
}
char buffer[1024];
int bytesWritten = 0;
int fifo = open("fifo", O_RDONLY);
signal(SIGALRM, alarm_handler);
alarm(1);
while(1) {
pause();
bytesWritten = read(fifo, buffer, 1024);
if (bytesWritten > 0)
write(1, buffer, bytesWritten);
}
return 0;
}
這“有效”,通過將 CPU 使用率設置為 0%。 但是,它使我的項目無法正常工作。 如果我足夠快地發送兩個命令,它只會注冊為一個命令。 這是由於暫停,當執行停止時,這些命令將被寫入 pipe 而不被讀取 - 分別寫入hello
和world
將注冊為一個hello world
而不是兩個單獨的 arguments。
有沒有其他方法可以降低 CPU 使用率?
@Cheatah 使用poll()
的建議非常有效。 這是現在建議更改的代碼:
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <poll.h>
int main () {
if (mkfifo("fifo", 0600) == -1) {
perror("Error on fifo");
return -1;
}
char buffer[1024];
int bytesWritten = 0;
int fifo = open("fifo", O_RDONLY);
struct pollfd *pfd = calloc(1, sizeof(struct pollfd));
pfd->fd = fifo;
pfd->events = POLLIN;
pfd->revents = POLLOUT;
while(1) {
poll(pfd, 1, -1);
bytesWritten = read(fifo, buffer, 1024);
if (bytesWritten == -1) {
perror("Error on read()");
exit(-1);
}
if (bytesWritten > 0)
write(1, buffer, bytesWritten);
}
return 0;
}
這讓我的 CPU 使用率為 0%,而且效果很好
為了防止這種忙等待情況,您的代碼中的最小更改是簡單地將服務器中的 fifo 以讀/寫而不是只讀方式打開:
int fifo = open("fifo", O_RDWR);
通過這種方式,您將始終打開 fifo 以供程序(服務器本身)寫入,因此當第一個客戶端關閉 fifo 時,讀取操作不會過早終止。
另一方面,如果您希望read()
因超時而阻塞,則使用poll()
會特別好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.