如何打断一个电话?

时间:2010-10-07 13:58:52

标签: c linux interrupt fread

我有以下情况:

有一个线程从具有fread调用的设备读取。只要没有数据从设备发送,此呼叫就会被阻止。 当我停止这个线程时,它仍然挂在这个线程内。

现在我在fread的手册页中找到了以下内容:

  

错误

     

在所有符合的系统上   单一UNIX规范,fread()   函数设置errno列出的   以下条件:

     

[EINTR]读取操作是   因收到a而终止   信号,没有传输数据。

这意味着有一种方法可以从不同的线程中断调用。但我不知道怎么做。有人能告诉我如何发送信号来中断这个电话吗?我需要发出什么信号?


更新08-10-10 09:25

我仍然没有工作。我用不同的信号尝试了kill()和pthread_kill()。但似乎没有什么能打断fread()调用。我唯一能做的就是杀死整个应用程序,但这不是我想要的。

6 个答案:

答案 0 :(得分:9)

<强> 1。信号:

许多其他人指出,使用信号会起作用。然而,正如许多其他人也指出的那样,这种方法有其缺点。

<强> 2。选择():

使用select()(或其他多路复用功能),可以阻止等待数据从多个文件描述符到达,并指定超时。

使用超时功能。每当select()返回时,检查一个全局变量以查看是否必须终止。如果你想立即反应,继续阅读。

第3。选择()和管道:

多个fds意味着您可以等待通过您提到的设备到达的数据,例如管道。

在创建线程之前,创建一个管道,然后让select()上的线程块监视设备和管道。无论何时要取消阻止选择设备是否有新数据,都要向管道发送一个字节。

如果select()告诉您由于数据通过管道到达而解锁,您可以清理并终止。请注意,此方法比信令方法更灵活,因为除了使用管道作为唤醒方法之外,您还可以使用它来传递有用的信息或命令。

<强> 4。选择(),管道和信号:

如果您正在使用多个进程并且不希望/无法传递管道,则可以将两个解决方案结合使用。创建一个管道并为SIGUSR1安装一个信号处理程序。在信号处理程序中,向管道发送一个字节。

每当进程发送SIGUSR1时,将调用该处理程序并取消阻塞select()。通过检查fdsets,您将知道除了您自己的程序发出信号之外没有其他原因。

答案 1 :(得分:4)

您真的想要阅读有关select(2)系统调用的信息,这将允许您查看该文件描述符上是否有可用数据,完全没有阻塞或仅仅阻止该设备。

答案 2 :(得分:3)

看看man 2 kill。 (或参见here

我觉得你不想这样做 - 大多数时候人们忽略了错误EINTR并再次阅读。您可能希望查看非阻塞读取。

答案 3 :(得分:2)

在主题中,不是使用fread进行屏蔽,而是使用select进行屏蔽。当select返回时,请检查“我是否已完成”变量。如果没有完成,您可以致电fread获取数据。

从另一个线程 - 想要停止fread线程 - 你可以设置“我完成”变量然后关闭fd,以便fread线程立即从select唤醒。 / p>

如果你的上下文禁止你关闭fd(你提到你正在读取设备,但是说你有一个你希望保持打开的套接字),你可以打开第二个fd,你从另一个线程写到醒来select

正如下面的评论中所建议的那样,关闭fd以唤醒select可能无法移植。您可以使用上面提到的第二种策略来实现更便携。

答案 4 :(得分:0)

您可以使用kill()系统调用。

<强>更新

原来我误读了你的问题。正如R.在下面指出的那样,kill()仅用于杀死进程,而不是线程。

答案 5 :(得分:0)

信号处理程序不会中断fread,除非它们被安装为中断,未处理的信号永远不会中断。 POSIX标准允许signal函数安装的处理程序默认中断或不中断(在Linux上默认为不中断),因此如果您需要特定行为,请使用{{1} }功能并指定所需的sigaction。特别是,您需要省略sa_flags标志。例如:

SA_RESTART

请注意,如果省略struct sigaction sa = { .sa_handler = dummy_func, .sa_flags = 0 }; sigaction(SIGUSR1, &sa, 0); ,则隐式为0,但我在初始化程序中明确地将其包括在内以进行说明。然后,您可以通过sa_flagsfread发送SIGUSR1来中断kill

相关问题