中断阻塞调用简单的代码下面举例说明我在醒来是在司机的呼叫阻塞线程的问题。我没有驱动程序源代码,但是如果驱动程序阻塞的物理设备发生电源中断,则需要唤醒线程才能关闭进程。从并行线程
实施例(见下面的代码):
main()
设置一个信号处理程序SIGINT
,启动一个子线程,然后进入无限循环的地方反复休眠模式唤醒,并打印出时醒来。子线程执行相同的操作,但每次唤醒时,它也会向该进程发送一个SIGINT
。 sleep()
被用作一个简单的阻塞呼叫。
运行代码显示了以下行为:
- 每次孩子线程被唤醒,它打印的“当”的消息(当它醒来的时候)。然后信号处理程序报告它收到了
SIGINT
。 - 每次“主”唤醒时,它打印的“当”的消息。
如下:
main: 0.127
Child: 0.127
SignalHandler: signum = 2
Child: 5.127
SignalHandler: signum = 2
main: 7.127
Child: 10.127
SignalHandler: signum = 2
main: 14.127
Child: 15.128
SignalHandler: signum = 2
Child: 20.128
SignalHandler: signum = 2
main: 21.127
.
.
.
我预计,通过该过程中收到的SIGINT
的结果,main()
会打破它的阻止呼叫sleep()
的。这将被视为main()
打印它'时'的消息。事实上,这正是我看看,如果我从壳型按Ctrl-C(SIGINT
)的行为。您可以在下面看到两个Ctrl-C中断。每一次,main()
确实摆脱它的阻止呼叫sleep()
:
main: 0.417
child: 0.417
SignalHandler: signum = 2
child: 5.417
SignalHandler: signum = 2
^C
SignalHandler: signum = 2
main: 6.664
child: 10.417
SignalHandler: signum = 2
main: 13.664
child: 15.418
SignalHandler: signum = 2
^C
SignalHandler: signum = 2
main: 16.680
child: 20.418
SignalHandler: signum = 2
main: 23.680
child: 25.418
SignalHandler: signum = 2
-----------守则---------------
// Compile using:
// g++ Test.cpp -o Test -g -lpthread -lrt
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
void When(const char *who) {
timespec sTimespec;
static long startSecond = -1;
clock_gettime(CLOCK_MONOTONIC, &sTimespec);
if (startSecond == -1)
startSecond = sTimespec.tv_sec;
sTimespec.tv_sec -= startSecond;
sTimespec.tv_nsec /= 1e+6; // only show milliseconds
printf("%s: %ld.%03ld\n", who, sTimespec.tv_sec, sTimespec.tv_nsec);
}
void SignalHandler(int signum) {
printf("SignalHandler: signum = %d\n", signum);
}
void *Child(void *pContext) {
char temp[256];
for (;;) {
When("Child");
kill(getpid(), SIGINT);
sleep(5);
}
}
int main(int argc, char **argv) {
pthread_t childThread;
signal(SIGINT, SignalHandler);
pthread_create(&childThread, NULL, Child, NULL);
for (;;) {
When("main");
sleep(7);
}
return 0;
}
所以好像当一个进程发送SIGINT
到自身时,信号被交付(见第一个结果),但阻塞调用不被中断。从外部进程发送SIGINT
将传递信号,并阻止呼叫被中断。
其他的事情:
raise(SIGINT);
pthread_kill(mainThreadId, SIGINT); // where mainThreadId is resolved to pthread_self() from within 'main'
sprintf(temp, “kill -2 %d”, getpid()); system(temp);
我写了一个独立的程序(xkill)采用一个PID作为参数,并发送SIGINT
到PID。
然后:
sprintf(temp, “xkill %d”, getpid()); system(temp);
注:我可以运行从shell这个程序,并获得良好的/预期的行为。
在我看来,没有任何儿童(线程或进程)可以中断其父阻塞调用,即使它可以提供一个信号。
一个你能提供一些线索在这种情况呢?
对于我的真实代码,我需要以编程方式打破阻塞驱动程序调用,所以我可以干净地关闭。在我的真实代码中,子线程是设备运行状况监视器。
只是安排事情,所以该线程将只做无害的事情,当它爆发的功能,或许通过检查从取消标志的功能和设置返回取消标志。那么你不必关心线程是否脱离函数。 –
进程中的任何线程都可以用来传递信号;如果信号传送到同一个线程,阻塞呼叫只会中断。 (即使信号处理程序有一个空的主体。)因此,您需要阻止除希望中断的那个线程(即阻塞呼叫)之外的所有线程中的信号,或者可以使用信号处理程序来转发信号到期望的线程(除非已经被期望的线程捕获)。 Paul Griffiths已经回答了后者的一个很好的例子,尽管我猜想一个更简单/更直接的例子是可能的。 –