我正在尝试在文件描述符上进行I / O时接收信号。该程序在不执行I / O时需要做其他事情,因此不能使用select(2)。
当我在下面运行示例代码时,即使在stdin上没有数据,它也会从处理程序内部以最快的速度打印消息。甚至更奇怪的是,siginfo_t结构中报告的文件描述符因运行而异。我只将其设置为stdin(fd
0); 处理程序为什么还要报告其他任何值?有时我看到0,有时我看到1,大多数时候我看到“?”,这表示0、1或2以外的值。
这是在OpenSUSE 12.3,Linux内核3.7.10-1.16上,但是我看到在带有其备用内核的CentOS 6.4上似乎是相同的问题。
我在处理程序中使用write,因为signal(7)表示它是可重入的,因此在信号处理程序中使用是合法的。这也是为什么我不打印sinfo->
si_fd的值的原因。snprintf不是可重入的。有一阵子我怀疑使用SIGIO的stdio库,这就是为什么示例程序中的任何地方(除了库函数err(3)之外)都没有stdio调用的原因。
感谢您花时间阅读我的代码。
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <err.h>
#include <errno.h>
int needRead = 0;
const unsigned int bufsize = 256;
void handler(int sig, siginfo_t *sinfo, void *value)
{
char *cp;
cp = "in handler. fd: ";
write(2, cp, strlen(cp));
switch(sinfo->si_fd) {
case 0: cp = "0\n"; break;
case 1: cp = "1\n"; break;
case 2: cp = "2\n"; break;
default: cp = "?\n"; break;
}
write(2, cp, strlen(cp));
needRead = 1;
}
int main(int argc, char *argv[])
{
struct sigaction act;
unsigned int counter = 0;
int flags;
char *outp = ".";
/* set up the signal handler for SIGIO */
act.sa_sigaction = handler;
act.sa_flags = 0;
act.sa_flags = SA_RESTART;
sigemptyset(&act.sa_mask);
if (sigaction(SIGIO, &act, NULL) == -1)
err(1, "attempt to set up handler for SIGIO failed");
/* arrange to get the signal */
if (fcntl(0, F_SETOWN, getpid()) == -1)
err(1, "fnctl to set F_SETOWN failed");
flags = fcntl(0, F_GETFL);
if (flags >= 0 && fcntl(0, F_SETFL, flags | O_ASYNC ) == -1)
err(1, "fnctl F_SETFL to set O_ASYNC failed");
while (1) {
char in_buf[bufsize];
int nc;
counter++;
write(STDERR_FILENO, outp, strlen(outp));
if (needRead) {
needRead = 0;
if ((nc = read(STDIN_FILENO, in_buf, bufsize)) == -1) {
err(1, "read from stdin failed");
} else {
outp = "Read '";
write(STDERR_FILENO, outp, strlen(outp));
write(STDERR_FILENO, in_buf, nc);
outp = "'\n";
write(STDERR_FILENO, outp, strlen(outp));
}
}
}
return 0;
}
啊,有趣。
简短的答案是,因为stdin是 可写的 ,所以SIGIO反复到达stdin ,并且单独地,您的SIGIO传递设置不正确。
为什么si_fd显然不可靠?
首先,您需要先指定SA_SIGINFO sa_flags
才能安全使用sa_sigaction
处理程序。
其次,#define _GNU_SOURCE
在Linux
为您填充si_fd
(和si_band
)之前,您需要将F_SETSIG显式地添加到SIGIO
。有点傻,恕我直言,但事实如此。si_fd
如您所发现的,没有这个,传入的值就没有意义。
为什么要反复交付SIGIO?
我猜您程序的stdin是从您调用的shell继承的,我猜它是一个终端设备并且是可写的。就像fd 0会持续 select(2)
可写一样,它也会连续为您生成SIGIO。
无论如何,si_band
保持答案。启用F_SETSIG,,#include <poll.h>
并检查si_band
POLLIN,POLLOUT等,以确定哪些I / O事件使信号跳闸。
真的,stdin是可写的吗?
是的 尝试以下比较:
$ [ -w /dev/stdin ] && echo Yes, stdin is writeable
Yes, stdin is writeable
# Endless SIGIOs
$ ./my-sigio-prog
^C
# No SIGIO
$ ./my-sigio-prog < /dev/null
# Two SIGIOs, after a delay. One for line-buffered "foo\n" and one for EOF
$ { sleep 3; echo foo; sleep 3; } | ./my-sigio-prog
我想开发一个模块化的应用程序,使用MySql数据库,Java11和Spring启动。在我添加模块描述符之前,这个应用程序运行得非常好;所以我只能猜测我在module-info.java中丢失了一些东西,但我不知道它是什么。我感谢任何帮助。这是我的密码 波姆。xml 应用yml module-info.java 使用者JAVA UsersRepository.java 用户资源。JAVA 演示应用程
我已经运行了数据库,并且可以使用swing GUI连接到它。但当我尝试运行我的应用程序时,我得到一个启动错误。以下是详细内容: 1:错误- 信息:初始化Spring根WebApplicationContext[ERROR][pool-2-thread-1 05:20:08](JDBCExceptionReporter.java:LogException:101)无法从基础数据库获取连接![错误][
我的主要活动是 运行时的错误为 w/system.err:org.json.jsonException:org.json.jsonobject.get(jsonobject.java:392)上的描述没有值w/system.err:at org.json.jsonobject.getStri 列表项 ng(JSONObject.java:553) w/system.err:org.json.jso
我想从Kafka的主题消费事件后,他们到达的时间。我希望使用事件的时间在消息的有效负载中。在Kafka那里有可能实现那样的事情吗?它的缺点是什么? 实际示例:一条消息M在12:10产生,在12:11到达我的Kafka主题,我希望消费者在12:41(到达后30分钟)轮询它
问题内容: 这与“没有单独的联接表的hibernate@OneToMany”类似,因为我需要一个没有联接表的@OneToMany关系。但是,我也不想定义逆关系。删除相反的内容似乎会导致自动生成联接表…是否有解决方法? 问题答案: 在JPA 2.0+中,您可以使用@JoinColumn作为避免生成联接表的方法。 尝试一下。 更新 上面提供的信息摘自EJB 3.0o’illy书(查找@JoinColu
我正在尝试从系统中读取。输入是这样的:第一个数字是测试用例的数量,然后是整数,然后是一些行。 问题是,尽管循环中存在条件,但当我完成最后一个测试时,while循环不会退出。