我想在C中不断读取一个fifo管道。 我的代码示例有效,但是因为我使用while(1)我的一个CPU核心始终是100%。
所以我的问题:是否有更顺畅的方式来读取fifo,而不会杀死CPU?
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
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;
}
答案 0 :(得分:2)
您有3种方法可以处理它: -
您可以在从FIFO读取时使用阻止模式。
最简单的方法是在while循环中使用sleep()暂停线程一段时间,这会暂时减少cpu负载。
您可以使用信号&amp;中断,写入器可以在向FIFO写入内容时发送信号。读取器可以被挂起,直到从FIFO和FIFO的写入器接收到信号。执行读操作直到FIFO结束并再次暂停。
答案 1 :(得分:1)
在这种情况下,我会使用select()
进行投票。你可以这样做:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/select.h>
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[63] = '\0';
printf(buffer);
}
}
close(fd);
return 0;
}
它应该适用于使用mkfifo()
创建的FIFO文件。
您还可以在函数调用中使用NULL
而不是timeout
设置无限超时。
这将大大降低CPU利用率,并允许您只读取实际数据。
请注意,如果您使用简单文件而不是FIFO,select()
函数将永远等待它更新,因为简单文件随时可以读取。
您还可以阅读以下文章以获取更多信息:select, pselect, poll