I've to read program log file and to do that I wanted to use select() and read()
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
int fd = -1;
fd_set fds;
struct timeval tv;
int rc;
char buffer[4096];
char * log_path = "/home/mich/a.txt";
if((fd = open(log_path,O_RDONLY) ) == -1 )
{
printf("error\n");
return -1;
}
while(1)
{
FD_ZERO(&fds);
FD_SET(fd,&fds);
tv.tv_sec = 2;
tv.tv_usec = 0;
rc = select(fd+1, &fds, NULL, NULL, &tv);
if (rc < 0) {
printf("failed\n");
continue;
} else if (rc > 0 && FD_ISSET(fd,&fds)) {
printf("read\n");
} else {
printf("timeout\n");
continue;
}
while ((my_getline(buffer,sizeof(buffer),fd)) > 0)
{
printf("%s",buffer);
}
}
close(fd);
}
my_getline is a function which uses read().
Output:
read
aaa
read
read
read
read
read
bbb
read
read
read
read
...
where aaa and bbb are lines from read file.
What is wrong in this program?
select
tells you that there is something waiting on fd
. This doesn't have to be a line, it could be a single byte, or the information that the end of the file has been reached. Add puts("####");
at the end of the outer while
loop to see how your code processes the input file.
To see how to keep reading a file that other processes are appending to, look at the source code for one of the free implementations of the unix tail
utility (specifically its -f
option). The traditional implementation is to read the whole file, sleep for a small interval (1 second in tail
), and repeat from the position where you left off after the last read. A more modern, more reactive, less resource-consuming, but less portable approach uses a file change notification API (inotify under Linux, kqueue under *BSD, ...).