gpt4 book ai didi

c - O_ASYNC 停止生成 SIGIO

转载 作者:IT王子 更新时间:2023-10-29 00:58:42 28 4
gpt4 key购买 nike

这有点长...对于初学者,我使用的是 Linux 2.6.33,gcc 4.4.4。

我写了一个小程序,它创建一个命名管道并读取它,直到它看到一个特定的字符串,然后它摆脱 FIFO,并重新执行自己。

#include<unistd.h>
#include<fcntl.h>
#include<signal.h>
#include<sys/types.h>
#include<sys/stat.h>
int fifo;
#define put(x) write(1, x, (sizeof x)-1)
void reader(int a)
{
char buf[26];
int n;
while((n=read(fifo, buf, 25))>0){
buf[25] = '\0';
if(!strncmp(buf, "moo", 3)){
put("exec()-ing\n");
close(fifo);
unlink("lefifo");
execl("/home/dave/a.out", "a.out", 0);
}
write(1, buf, n);
}
}

main()
{
signal(SIGIO, reader);
mknod("lefifo", 0600|S_IFIFO,0);
fifo = open("lefifo", O_RDONLY|O_NONBLOCK );
fcntl(fifo, F_SETOWN, getpid());
fcntl(fifo, F_SETFL, O_ASYNC);

for(;;)
pause();
}

当编译并在后台运行时,我可以回显到 lefifo 并且它按预期工作,直到我输入以“moo”开头的字符串。以下示例 session :

$ gcc fifo.c 
$ ./a.out&
$ echo klar > lefifo
klar
$ echo moo > lefifo
exec()-ing
$ echo klar2 > lefifo
$ echo where did you go > lefifo
$ echo moo > lefifo
$ pkill a.out

生成此跟踪(一些脂肪修剪):

execve("./a.out", ["./a.out"], [/* 36 vars */]) = 0
mknod("lefifo", S_IFIFO|0600) = 0
open("lefifo", O_RDONLY|O_NONBLOCK) = 3
getpid() = 3945
fcntl(3, F_SETOWN, 3945) = 0
fcntl(3, F_SETFL, O_RDONLY|O_ASYNC) = 0
pause() = ? ERESTARTNOHAND (To be restarted)
--- SIGIO (I/O possible) @ 0 (0) ---
read(3, "klar\n"..., 25) = 5
write(1, "klar\n"..., 5) = 5
read(3, ""..., 25) = 0
sigreturn() = ? (mask now [])
pause() = ? ERESTARTNOHAND (To be restarted)
--- SIGIO (I/O possible) @ 0 (0) ---
read(3, "moo\n"..., 25) = 4
write(1, "exec()-ing\n"..., 13) = 13
close(3) = 0
unlink("lefifo") = 0
execve("/home/dave/a.out", ["a.out"], [/* 36 vars */]) = 0
mknod("lefifo", S_IFIFO|0600) = 0
open("lefifo", O_RDONLY|O_NONBLOCK) = 3
getpid() = 3945
fcntl(3, F_SETOWN, 3945) = 0
fcntl(3, F_SETFL, O_RDONLY|O_ASYNC) = 0
pause() = ? ERESTARTNOHAND (To be restarted)
--- SIGTERM (Terminated) @ 0 (0) ---

如您所见,第一次创建 FIFO 没有任何问题,SIGIO 生成得很好;但在 exec() 之后,新的 FIFO 不会产生任何信号。旧的显示关闭成功,似乎删除成功。

我很困惑为什么它会这样。有什么想法吗?

最佳答案

当您使用 signal() 安装信号处理程序时,在默认配置中,glibc 将提供 BSD 信号语义:该信号将在信号处理程序执行时被阻塞,并在它返回时解除阻塞。

当您从信号处理程序调用 exec() 时,信号处理程序不会返回,因此 SIGIO 仍处于阻塞状态。进程信号掩码在 exec() 上继承,因此它在进程的新实例中保持阻塞状态。

main() 开始时使用 sigprocmask() 显式解除阻止 SIGIO,您应该会得到您想要的行为。

关于c - O_ASYNC 停止生成 SIGIO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7034175/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com