“重写‘fgets’以包含一个警报,这样如果 5 秒后用户没有输入任何数据,‘fgets’将返回一个指向 NULL 的指针(超时)”
这是一项大型家庭作业的问题,我们才刚刚开始研究信号、捕捉、处理等。话虽如此,这本书和讲座幻灯片都缺少这方面的内容......
我想到了创建处理程序来捕获此类异常的想法,并且我了解警报的工作原理,但我不了解该接口(interface)将如何工作。
现在只想着“fgets”……如果我只是在所有其他工作完成之前(就在我的返回指针之前)在其中设置一个警报:
char *fgets(//...//)
{
alarm(5);
char * to_return = NULL;
//...//
如果在用户输入数据之前警报响起,我的处理程序是否可以“返回 NULL”?处理程序完成后,执行不会在“fgets”内恢复吗?我想我对处理程序在函数内部可以做什么感到困惑(即它可以强制函数返回一些值,它可以修改函数内声明的变量,它可以强制跳转到不同的函数调用,等等)
首先,信号处理程序是一个独立执行线程。当发出信号时,代码的“正常”执行会中断,信号处理程序会执行,一旦处理程序返回,代码的执行就会从中断点恢复。
因此,1) 您的信号处理程序不能影响从您的 fgets()
返回(至少不能直接影响),并且 2) 它不能返回值。 (您可能会注意到安装信号处理程序的 signal()
函数需要一个指向函数的指针,该函数以整数作为参数并且具有void
返回类型。
信号处理程序可以做的是设置一个值。标准(C99,“信号处理”一章,7.14.1.1 (5))对此表示:
If the signal occurs other than as the result of calling the abort
or raise
function, the
behavior is undefined if the signal handler refers to any object with static storage duration
other than by assigning a value to an object declared as volatile sig_atomic_t
, or
the signal handler calls any function in the standard library other than the abort
function, the _Exit
function, or the signal
function with the first argument equal to
the signal number corresponding to the signal that caused the invocation of the handler.
这意味着,您可以声明一个 volatile sig_atomic_t
类型的变量,您的 fgets()
和您的信号处理程序都可以“看到”它,将其初始化为一个默认值,并让信号处理程序更改该值,以便您的 fgets()
可以看到信号已触发。
当然,如果您的 fgets()
等到用户输入内容,它甚至会在信号触发后等待...如何解决这个问题取决于您如何进行输入.您要么对输入使用非阻塞检查,例如 getch()
(这不是 ISO/ANSI C),要么您依赖于 read()
的行为R. 提到(它依赖于 fgets()
下的 POSIX 层),或其他。我无法考虑严格的 ISO/ANSI C 方法来执行此操作,因此这取决于您在类(class)中已经学过/做过的事情。
哦,如果你有勇气,告诉你的导师,将标准函数重新定义为不同的行为是一个真的坏主意(避免称他为“愚蠢”)。如果您想要一个不是真正的 fgets()
的 fgets()
,请给它一个不同的名称,例如fgets_timed()
。