O_ASYNC停止生成SIGIO

Dav*_*ave 4 c linux signals fifo

这有点长...对于初学者我在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();
}
Run Code Online (Sandbox Code Playgroud)

编译后,在后台运行时,我可以回显lefifo并按预期工作,直到我输入以"moo"开头的字符串.以下示例会话:

$ 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
Run Code Online (Sandbox Code Playgroud)

生成此痕迹(一些脂肪修剪):

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) ---
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,第一次,创建FIFO没有问题,SIGIO生成就好了; 但exec()新FIFO 后不会产生任何信号.旧的显示成功关闭,似乎成功删除.

我很难过为什么它会这样做.有任何想法吗?

caf*_*caf 5

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

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

明确解除SIGIO使用sigprocmask()在开始main()和你应该得到的是你以后的行为.