簡體   English   中英

在沒有 100% CPU 使用率的情況下,如何繼續讀取名為 pipe 的內容?

[英]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 而不被讀取 - 分別寫入helloworld將注冊為一個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()會特別好。

請參閱: https://stackoverflow.com/a/23499902/6874310

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM