【问题标题】:Detect if a file descriptor with O_NONBLOCK is still valid in a FFI scenario检测带有 O_NONBLOCK 的文件描述符在 FFI 场景中是否仍然有效
【发布时间】: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 不会失效。

标签: c linux smalltalk ffi


【解决方案1】:

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

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

#define errno (*__errno_location ())

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

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

【讨论】:

  • 非常感谢。 __errno_location 调用有效,现在我可以访问errno。对于任何有相同问题的人:您必须在 Squeak 中定义一个派生自 ExternalStructure 的单独类,否则您最终会得到一个不透明的 ExternalData 指针。字段:fields ^#((errno 'long')),FFI 调用:&lt; cdecl: StructureName* '__errno_location' () module: 'libc.so.6' &gt;
猜你喜欢
  • 1970-01-01
  • 2012-09-02
  • 2013-03-10
  • 2021-05-08
  • 2011-02-22
  • 2016-04-18
  • 1970-01-01
  • 2019-06-11
  • 2011-04-08
相关资源
最近更新 更多