如何在C中不断读取FIFO

我想在C中不断读取一个fifo管道。我的代码示例有效,但是因为我使用while(1)我的一个CPU核心始终处于100%。

所以我的问题是:有没有更顺畅的方式来读取fifo,而不会杀死CPU?

#include  #include  #include  #include  #include  #include  bool suffix (char* base, char* str) { int blen = strlen(base); int slen = strlen(str); return (blen >= slen) && (0 == strcmp(base + blen - slen, str)); } bool prefix(const char *pre, const char *str) { return strncmp(pre, str, strlen(pre)) == 0; } void chomp(char *s) { while(*s && *s != '\n' && *s != '\r') s++; *s = 0; } int main(int argc, char *argv[]) { int fifo, c=0; char buf[200]; char fifo_name[] = "/var/log/proftpd_log_all.fifo"; fifo = open(fifo_name, O_RDONLY|O_NONBLOCK); while (1) { if (read(fifo, &buf, sizeof(char)*200) > 0) { if (prefix("[STOR]",buf)) { //printf("%s \n", buf); if (strstr(buf, ".jpf") != NULL) { //... } } } } printf("exit"); close(fifo); return 0; } 

你有3种处理方法: –

  1. 从FIFO读取时可以使用阻塞模式。

  2. 最简单的方法是在while循环中使用sleep()暂停线程一段时间,这会暂时减少cpu负载。

  3. 您可以使用信号和中断,写入器可以在向FIFO写入内容时发送信号。读取器可以暂停,直到从FIFO的写入器接收到信号并执行读取操作直到FIFO结束并再次暂停。

在这种情况下,我会使用select()进行轮询。 你可以这样做:

 #include  #include  #include  #include  int main() { fd_set readCheck; fd_set errCheck; char buffer[64]; struct timeval timeout; int rv; int fd = open("./fifo.test", O_RDONLY | O_RSYNC); FD_ZERO(&readCheck); FD_ZERO(&errCheck); while (1) { FD_SET(fd, &readCheck); FD_SET(fd, &errCheck); timeout.tv_sec = 1; timeout.tv_usec = 0; rv = select(fd, &readCheck, NULL, &errCheck, &timeout); if (rv < 0) { printf("Select failed\r\n"); break; } if (FD_ISSET(fd, &errCheck)) { printf("FD error\r\n"); continue; } if (FD_ISSET(fd, &readCheck)) { memset(buffer, 0, sizeof(buffer)); rv = read(fd, buffer, sizeof(buffer)); if (rv < 0) { printf("Read failed\r\n"); break; } buffer[64] = '\0'; printf(buffer); } } close(fd); return 0; } 

它应该适用于使用mkfifo()创建的FIFO文件。 您还可以在函数调用中使用NULL而不是timeout设置无限超时。

这将大大降低CPU利用率,并允许您只读取实际数据。 请注意,如果您使用简单文件而不是FIFO,则select()函数将永远等待其更新,因为简单文件始终可以读取。

您还可以阅读以下文件以获取更多信息: select, pselect, poll