从输入中读取C/UNIX(受字符数和超时限制) [英] C/UNIX read from input (limited by char count and timeout)
问题描述
在学习决赛时,我发现了一个非常有趣的问题.这就是我想要编写的代码.
while studying for my finals I found a very interesting questing. This is what I desire to code.
程序将stdin读入缓冲区(具有固定大小).当缓冲区已满时,程序会将其打印到文件中.但是,如果缓冲区没有在固定的时间(超时)内被填充,程序将打印到文件[TIMEOUT]
,其余的缓冲区将被打印(当前已读取)
Program read stdin into buffer (of fixed size). When buffer is full, program prints it to file. But if buffer isn't filled in fixed time (timeout), program prints to file [TIMEOUT]
and the rest of buffer (currently read)
第一个示例:
buffer_size = 5;超时= 4;
buffer_size = 5; timeout = 4;
$ while : ; do printf 1; sleep 1; done | ./a.out
应该写[TIMEOUT]1111[TIMEOUT]1111[TIMEOUT]1111
等,因为while循环仅写4个字符(在4秒内).
should write [TIMEOUT]1111[TIMEOUT]1111[TIMEOUT]1111
etc. because while-loop writes only 4 chars (within 4 second limit).
第二个示例
buffer_size = 3;超时= 5;
buffer_size = 3; timeout = 5;
$ while : ; do printf 1; sleep 1; done | ./a.out
应该写111 111 111
等,因为while循环写了3个字符(在3秒内<5秒以内),所以永远不会发生超时.
should write 111 111 111
etc. because while-loop writes 3 chars (within 3 seconds < 5 sec limit) so timeout never happens.
我正在尝试使用poll
对其进行编码,但是我不知道如何找出所有字符是否已写入或仅一个字符.我也不能卡在read(0, buffer, buffer_size)
上,因为我会错过超时.可能吗?我想这是我们的老师指出的很好的练习.
I'm trying to code it using poll
but I don't know how to find out, whether all chars have been written or only one. I can't also get stuck on read(0, buffer, buffer_size)
as I would miss timeout. Is it even possible? I guess it is as our teacher pointed it out as a good excersice.
当然,繁忙的等待是不可接受的,只允许使用经典的POSIX系统调用(轮询,选择,读取,写入,打开...).
Of course, busy wait is unacceptable, only classic POSIX syscalls allowed (poll, select, read, write, open...).
有人可以提示我吗?我不知道如何管理这种行为,并且堆栈溢出过多,谷歌也没有给我答案(或者也许我只是不知道要搜索什么)
Could anybody hint me, please? I have no clue how to manage this behaviour and neighter stackoverflow nor google gave me answer (or maybe I just don't know what to search for)
预先感谢
推荐答案
谢谢大家,我以其他方式解决了这个问题(但仍然没有忙碌的等待时间).我附上下面的代码供更多的学生使用:)
thanks guys, I figured it out in other way (but still no busy-wait). I attach the code below for further students :)
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <libgen.h>
#include <err.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <time.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <errno.h>
extern char ** environ;
/*
usage:
$ while : ; do printf 1; sleep 1; done | XTIMEOUT=4 XSIZE=5 ./a.out
[TIMEOUT]1111[TIMEOUT]1111[TIMEOUT]1111...
$ while : ; do printf 1; sleep 1; done | XTIMEOUT=5 XSIZE=3 ./a.out
111...
*/
uint64_t
now()
{
struct timeval tv;
gettimeofday(&tv, NULL);
double time_in_mill = (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000;
return (uint64_t) time_in_mill;
}
int
main(int argc, char ** argv) {
// ----------------------------------
// boring stuff
size_t timeout = 11 * 1000;
size_t buffer_size = 10;
char * tmp_env;
if ((tmp_env = getenv("XTIMEOUT")) != NULL) {
timeout = atoi(tmp_env) * 1000;
}
if ((tmp_env = getenv("XSIZE")) != NULL) {
buffer_size = atoi(tmp_env);
}
// ----------------------------------
// fun starts here
// buffers
char * buffer = (char *) malloc(buffer_size * sizeof(char));
char * buffer2 = (char *) malloc(buffer_size * sizeof(char));
// set stdin non-blocking
int saved_flags = fcntl(0, F_GETFL);
fcntl(0, saved_flags | O_NONBLOCK);
// poll structure
struct pollfd ufds[1];
ufds[0].fd = 0;
ufds[0].events = POLLIN;
int rv, n, k;
size_t pos = 0;
uint64_t start_time;
int rem_time = timeout;
for (;;) {
start_time = now();
//printf("pollig for %d\n", rem_time);
rv = poll(ufds, 1, rem_time);
if (rv == -1) { // err
err(1, "poll");
}
else if (rv == 0) { // timeout
write(1, "[TIMEOUT]", 9);
write(1, buffer, pos);
pos = 0;
rem_time = timeout;
}
else { // regular
if (ufds[0].revents & POLLIN) { // real action
if ((n = read(0, buffer2, buffer_size-pos)) == -1) { // read up to free space
err(1, "read");
}
for (k = 0; k < n; ++k) { // copy (maybe strcp)
buffer[k+pos] = buffer2[k];
}
pos += n; // pos has changed
if (pos == buffer_size) { // buffer is full -> write it out and set new timeout
write(1, buffer, buffer_size); write(1, "", 1);
pos = 0;
rem_time = timeout;
}
else { // still not enough, make timeout shorter (by the length of computation)
rem_time = rem_time - now() + start_time;
}
}
else { // poll failed!
err(1, "false alarm");
}
}
}
free(buffer);
free(buffer2);
return (0);
}
这篇关于从输入中读取C/UNIX(受字符数和超时限制)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!