检测具有O_NONBLOCK的文件描述符在FFI场景中是否仍然有效

时间:2016-05-05 23:41:35

标签: c linux smalltalk ffi

如果我有一个用open (2)打开的文件描述符,然后使用FFI(外部函数接口)使用O_NONBLOCK设置为fcntl (2)

这意味着几乎每次调用read (2)都会返回-1,errno设置为EAGAIN,这意味着此时没有数据可用。

可悲的是,我使用的FFI无法访问errno变量,因此我无法确定是否返回-1值,因为没有数据或文件句柄不再有效。

所以我试图以某种方式确定文件描述符是否仍然有效而无需阅读errno。我already tried all the answers with fcntl from this question,但他们不工作,永远不会返回-1。

也许这是因为我正在阅读设备文件:/dev/input/js0

我可以调用另一个函数来告诉我文件描述符是否无效? (在上面的问题中有人提到poll,但我不确定这是什么意思。)

我正在使用Squeak FFI,不允许添加任何自定义C包装器。我正在尝试访问游戏手柄并从中读取按钮信息,这是一个可选的任务。

我用fcntl尝试的Smalltalk源代码:

fcntl的FFI(在班级Gamepad中定义):

manipulateFileHandle: fileHandle command: command
    < cdecl: long 'fcntl' ( long long ) module: 'libc.so.6' >
    ^ self externalCallFailed

然后在另一种方法中,我称之为:

| handleTest |
handleTest := Gamepad manipulateFileHandle: externalFileHandle command: 1.
Transcript show: handleTest; cr.

command 1是F_GETFD,读取文件描述符标志。但即使拔掉游戏手柄,handleTest也永远不会是-1。

1 个答案:

答案 0 :(得分:3)

在GNU / Linux系统上,libc包含函数__errno_location(),它返回errno变量的地址。您的FFI应该能够调用该函数,然后取消引用代表int *的地址。

在GCC发明线程局部变量的语法之前,允许多线程代码安全地操作errno的技术是将其定义为:

#define errno (*__errno_location ())

该函数将返回一个线程本地地址。在您的Linux系统上,如果您对使用gcc -E的C代码使用errno,您将看到扩展。

  

正如Barmar所解释的那样,fcntl()技术起作用。它永远不会返回-1的原因是因为您仍然持有有效的文件描述符。文件描述符在关闭之前不会变为无效。