gpt4 book ai didi

c - 为什么 fgets 在程序关闭和从 tail -f 传输数据时挂起?

转载 作者:太空宇宙 更新时间:2023-11-04 04:25:07 28 4
gpt4 key购买 nike

我正在使用 tail -f 读取日志并将数据传输到我的 ncurses 程序。

tail -f somelog | ./a.out

它工作正常,除了当我按下 q 时,程序不会退出,它只是挂起直到一个字节被写入正在尾部的文件。使用 cat somelog | 时不会发生这种情况./a.out,我猜这是因为没有被跟踪。

看起来是 while(fgets(buf, 1024, input) 行导致了问题。知道为什么以及如何解决它吗?谢谢

   // gcc app.c -lncurses
// tail -f logfile | ./a.out

#include <stdio.h>
#include <ncurses.h>
#include <fcntl.h>
#include <string.h>

void print_status(WINDOW * win, const char *str) {
init_pair(1, COLOR_RED, COLOR_WHITE);
clear();
mvwhline(win, 0, 0, ' ', COLS);
mvwaddnstr(win, 0, 0, str, COLS);
wrefresh(win);
}

void print_line(WINDOW * win, const char *str, int *i) {
init_pair(2, COLOR_RED, COLOR_BLACK);
if (*i > LINES - 2) {
*i = 1;
wclear(win);
}
mvwprintw(win, (*i)++, 0, str);
wrefresh(win);
}

int main() {
WINDOW *menu_win, *wi;
int i = 1, q = 1, fd1, fd2, is_atty = 1;
char buf[1024];

initscr();
clear();
halfdelay(5);

menu_win = newwin(1, COLS, 0, 0);
wi = newwin(LINES - 1, COLS, 1, 0);
keypad(menu_win, TRUE);

FILE *input = stdin;

if(!isatty(fileno(stdin))) {
is_atty = 0;
fd1 = open("/dev/tty", O_RDONLY);
fd2 = dup(fileno(stdin));
input = fdopen(fd2, "r");
freopen("/dev/tty", "r", stdin);
if(fileno(stdin) != 0) /* from ncurses dialog */
(void)dup2(fileno(stdin), 0);
close(fd1);
int flags = fcntl(fd2, F_GETFL);
// non-blocking fgets so getch works fine
fcntl(fd2, F_SETFL, flags|O_NONBLOCK);
}

print_status(menu_win, "Use arrow keys to go up and down");
while(q) {
switch(wgetch(menu_win)) {
case KEY_UP:
print_status(menu_win, "Moved up");
break;
case KEY_DOWN:
print_status(menu_win, "Moved down");
break;
case 'q':
q = 0;
break;
default:
if(is_atty) break;
while(fgets(buf, 1024, input) != NULL) {
print_line(wi, buf, &i);
}
break;
}
}
fclose(input);
close(fd2);
endwin();
return 0;
}

最佳答案

一旦您的代码调用 fgets(),它将在 fgets() 中保持阻塞状态,直到更多输入到达 - 或者管道关闭。

cat somelog | 不会发生这种情况./a.out 因为正如您所怀疑的那样,cat 并未挂起等待更多数据写入文件。 cat 不断发送数据然后退出,关闭管道并导致 fgets() 返回它缓冲的数据并等待更多或 NULL如果没有数据被读取。 tail -f ... 到达文件末尾时不会退出并关闭管道 - tail -f ... 只是等待更多数据写入拖尾的文件,因此您对 fgets() 的调用就在那里。

那为什么呢?因为 fgets() 在得到换行符或 EOF 之前不会返回。 Per the Linux man page (assuming you're running on Linux) :

fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. ...

关于c - 为什么 fgets 在程序关闭和从 tail -f 传输数据时挂起?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42451036/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com