【发布时间】:2016-05-05 23:41:35
【问题描述】:
如果我有一个使用 open (2) 打开的文件描述符,然后使用 FFI(外部函数接口)使用 fcntl (2) 设置为 O_NONBLOCK。
这意味着几乎每次调用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 包装器。我正在尝试访问 Gamepad 并从中读取按钮信息,这是一项可选任务。
我用 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,即使在拔掉游戏手柄之后也是如此。
【问题讨论】:
-
不允许写C代码?请在问题中说明此类限制。不得不通过反复审问你来发现所有不为人知的限制,这很糟糕。你在做什么系统?你可以编写不可移植的代码吗?因为大多数 libc 实现都有一个返回指向
errno的指针的函数。 -
您能否提供一个说明性程序来说明您的尝试,以便我们查看您是否引入了一些导致其无法工作的错误?
-
您的
fcntl想法应该奏效了。 FD关闭后,原来在什么设备上打开都没有关系。 -
你能在你的 smalltalk 代码中取消引用
int *吗?函数__errno_location()将返回errno变量的地址。 -
@NikontheThird 拔出设备不会使 FD 无效。在您调用
close()之前,FD 不会失效。