根据man ioctl
,使用open
打开文件描述符可能会导致不必要的副作用。该手册还指出,O_NONBLOCK
开头可以解决这些不必要的问题,但我似乎无法找到原因,也不知道实际的副作用是什么。有人可以解释一下吗?使用ioctl
是否始终可以使用O_NONBLOCK
打开文件描述符?
注意(来自
man ioctl
)为了使用此调用,需要一个打开的文件描述符。通常,open(2)调用会产生不必要的副作用,这是可以避免的 在Linux下通过给它O_NONBLOCK标志。
(*我知道O_NONBLOCK
意味着什么,但我不知道这是否会影响ioctl
调用它影响其他系统调用的方式。我的程序使用ioctl
从SPI总线写入和读取,与启用该标志完美配合。)
答案 0 :(得分:6)
查找答案的显而易见的地方是open(2)手册页,该页面位于O_NONBLOCK
的标题下,表示:
如果可能,文件以非阻塞模式打开。 open()和文件上的任何后续操作都没有 返回的描述符将导致调用进程 等待。
[...]
有关处理FIFO(命名管道)的信息,另请参阅fifo(7)。 有关O_NONBLOCK结合的影响的讨论 有强制文件锁和文件租约,请参阅fcntl(2)。
好的,这不是很有用,但让我们按照链接查看fifo(7)和fcntl(2)的手册页说:
通常,打开FIFO块直到另一端打开。
进程可以在非阻塞模式下打开FIFO。在这种情况下,打开 即使没有人在写入时打开,只读也会成功 对于只写而且只写开放将因ENXIO而失败(没有这样的 设备或地址),除非另一端已经打开。
在Linux下,打开FIFO进行读写将同时成功 阻塞和非阻塞模式。 POSIX将此行为保留为未定义。
所以这里至少有一个“不必要的副作用”:即使只是尝试打开FIFO也可能会阻止,除非你将O_NONBLOCK
传递给open()
来电(并打开它进行阅读)。
那么fcntl怎么样?正如open(2)手册页所述,要查看的部分是“强制锁定”和“文件租约”。它似乎对我来说,在这种情况下,强制锁是一个红色的鲱鱼 - 它们只会在试图实际读取或写入文件时导致阻塞:
如果进程尝试执行不兼容的操作 访问(例如,read(2)或write(2))在具有的文件区域上 不兼容的强制锁,那么结果取决于是否 O_NONBLOCK标志已启用其打开的文件描述。如果 O_NONBLOCK标志未启用,则系统调用将被阻止,直到 锁被删除或转换为兼容的模式 访问。
那么租约怎么样?
当一个进程(“租约破坏者”)执行open(2)或 truncate(2)与通过F_SETLEASE建立的租约冲突, 系统调用被内核阻止,内核通知 租赁持有人发送信号(默认为SIGIO)。 [...]
一旦租约被自愿或强行拆除或 降级,并假设租赁破坏者没有解除阻止 系统调用,内核允许租用断路器的系统调用 继续进行。
[...]如果 租约破坏者在调用open(2)时指定O_NONBLOCK标志, 然后调用立即失败,错误EWOULDBLOCK,但是 其他步骤仍然如上所述。
好的,这是另一个不必要的副作用:如果您尝试打开的文件有租约,open()
调用可能会阻止,直到租约持有人已经释放租约。
在这两种情况下,将O_NONBLOCK
传递给open()
避免了“不必要的副作用”,不出所料,open()
调用本身就会阻塞,直到某些其他进程完成某些操作。如果您引用的手册页中有任何其他种副作用,我不知道它们。
答案 1 :(得分:1)
来自 Linux系统编程,第2版,来自R. Love(强调我的):
O_NONBLOCK 如果可能,该文件将以非阻塞模式打开。 都不是 open()调用, 或任何其他操作将导致进程阻塞(休眠)I / O. 这个 行为可能只为FIFO定义。
有时,程序员不希望调用read()来阻塞 没有数据 可用。相反,他们更喜欢呼叫立即返回, 表明没有数据 是可用的。这称为非阻塞I / O;它允许应用程序 可能会执行I / O. 在多个文件上,没有阻塞,因此缺少可用的数据 另一个文件。
因此,额外的errno值值得检查:EAGAIN。
请参阅内核邮件列表中的this thread。