检测带有 O_NONBLOCK 的文件描述符在 FFI 场景中是否仍然有效
Detect if a file descriptor with O_NONBLOCK is still valid in a FFI scenario
如果我有一个使用 open (2)
打开的文件描述符,随后使用 FFI(外部函数接口)使用 fcntl (2)
设置为 O_NONBLOCK
。
这意味着几乎每次调用 read (2)
都会 return -1,errno
设置为 EAGAIN
,这意味着这次没有可用数据。
遗憾的是,我正在使用的 FFI 无法访问 errno
变量,因此我无法确定 -1 值是 returned 是因为没有数据还是因为文件句柄不是不再有效。
所以我试图以某种方式确定文件描述符是否仍然有效,而无需读取 errno
。我 already tried all the answers with fcntl
from this question,但它们不起作用,而且从不 return -1.
也许这是因为我正在读取设备文件:/dev/input/js0
?
我可以调用另一个函数来告诉我文件描述符是否无效吗? (在上面的问题中有人提到poll
,但我不确定这是什么意思。)
我正在使用 Squeak FFI,不允许添加任何自定义 C 包装器。我正在尝试访问游戏手柄并从中读取按钮信息,这是一项可选任务。
我用 fcntl 尝试的 Smalltalk 源代码:
fcntl
的 FFI(在 Class 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,即使在拔下游戏手柄后也是如此。
在 GNU/Linux 系统上,libc
包含函数 __errno_location()
,它 return 是 errno
变量的地址。您的 FFI 应该能够调用该函数,然后取消引用表示 int *
.
的地址
在 GCC 发明线程局部变量的语法之前,允许多线程代码安全操作 errno
的技术是将其定义为:
#define errno (*__errno_location ())
该函数将return一个线程本地地址。在您的 Linux 系统上,如果您在使用 errno
的 C 代码上使用 gcc -E
,您将看到扩展。
As explained by Barmar, the fcntl()
techniques work. The reason it never returned -1
was because you were still holding a valid file descriptor. A file descriptor does not become invalid until it is closed.
如果我有一个使用 open (2)
打开的文件描述符,随后使用 FFI(外部函数接口)使用 fcntl (2)
设置为 O_NONBLOCK
。
这意味着几乎每次调用 read (2)
都会 return -1,errno
设置为 EAGAIN
,这意味着这次没有可用数据。
遗憾的是,我正在使用的 FFI 无法访问 errno
变量,因此我无法确定 -1 值是 returned 是因为没有数据还是因为文件句柄不是不再有效。
所以我试图以某种方式确定文件描述符是否仍然有效,而无需读取 errno
。我 already tried all the answers with fcntl
from this question,但它们不起作用,而且从不 return -1.
也许这是因为我正在读取设备文件:/dev/input/js0
?
我可以调用另一个函数来告诉我文件描述符是否无效吗? (在上面的问题中有人提到poll
,但我不确定这是什么意思。)
我正在使用 Squeak FFI,不允许添加任何自定义 C 包装器。我正在尝试访问游戏手柄并从中读取按钮信息,这是一项可选任务。
我用 fcntl 尝试的 Smalltalk 源代码:
fcntl
的 FFI(在 Class 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,即使在拔下游戏手柄后也是如此。
在 GNU/Linux 系统上,libc
包含函数 __errno_location()
,它 return 是 errno
变量的地址。您的 FFI 应该能够调用该函数,然后取消引用表示 int *
.
在 GCC 发明线程局部变量的语法之前,允许多线程代码安全操作 errno
的技术是将其定义为:
#define errno (*__errno_location ())
该函数将return一个线程本地地址。在您的 Linux 系统上,如果您在使用 errno
的 C 代码上使用 gcc -E
,您将看到扩展。
As explained by Barmar, the
fcntl()
techniques work. The reason it never returned-1
was because you were still holding a valid file descriptor. A file descriptor does not become invalid until it is closed.