我目前正在构建使用epoll
的内容。它的工作非常好,但是当基础epoll
关闭时,如果文件描述符从fd
中删除,则会收到通知。
epoll
关闭后,有没有办法从fd
收到通知?
答案 0 :(得分:-1)
您需要注意epoll_wait()
何时返回-1
,然后检查errno
值,看它是否与EBADF
匹配。
有关详细信息,请参阅man epoll_wait()
,man errno
。
答案 1 :(得分:-1)
不。文件描述符一旦关闭,它就不再可用于内核在新文件描述符中使用的任何内容。一旦您因新的open(2)
,create(2)
,socket(2)
等系统调用而无法再次获取,系统调用将其用作参数任何系统调用(包括select(2)
和epoll(2)
)
内核已经释放了进程结构中的文件描述符条目,因此使用它无效。
如果你关闭它,你可以从epoll(2)
得到一些东西的唯一方法就是你有两个线程,并且当你在另一个线程中等待它时,你close(2)
一个线程中的文件描述符。这次你可以立即从epoll(2)
系统调用返回,可能有一些错误(我没有测试过这个),但我认为这不是你的场景。
答案 2 :(得分:-1)
不。这是一个Zig程序来演示:
const std = @import("std");
pub fn main() !void {
const epollfd = blk: {
const rc = std.os.linux.epoll_create1(std.os.linux.EPOLL_CLOEXEC);
const err = std.os.linux.getErrno(rc);
if (err != 0) return error.EpollCreateFailed;
break :blk @intCast(i32, rc);
};
defer std.os.close(epollfd);
var pipe: [2]i32 = undefined;
{
const rc = std.os.linux.pipe2(&pipe, std.os.linux.O_CLOEXEC);
const err = std.os.linux.getErrno(rc);
if (err != 0) return error.PipeCreateFailed;
}
var ev: std.os.linux.epoll_event = undefined;
ev.events = std.os.linux.EPOLLIN | std.os.linux.EPOLLET;
ev.data.fd = pipe[0];
{
const rc = std.os.linux.epoll_ctl(epollfd, std.os.linux.EPOLL_CTL_ADD, pipe[0], &ev);
const err = std.os.linux.getErrno(rc);
if (err != 0) return error.EpollCtlFailed;
}
const thread = try std.os.spawnThread(pipe[0], threadStart);
var events: [10]std.os.linux.epoll_event = undefined;
const nfds = blk: {
std.debug.warn("epoll wait\n");
const rc = std.os.linux.epoll_wait(epollfd, &events, @intCast(u32, events.len), -1);
std.debug.warn("epoll wakeup\n");
const err = std.os.linux.getErrno(rc);
if (err != 0) return error.EpollWaitFailed;
break :blk rc;
};
if (nfds != 1) return error.NotExactly1FileDescriptor;
std.debug.assert(events[0].data.fd == pipe[0]);
thread.wait();
}
fn threadStart(fd: i32) void {
std.os.time.sleep(1, 0);
std.debug.warn("close fd\n");
std.os.close(fd);
}
它输出:
epoll wait
close fd
^C
(我必须用Ctrl + C杀死它,因为它永远不会醒来。)
这是strace的输出:
execve("./test", ["./test"], 0x7fff311ff208 /* 122 vars */) = 0
epoll_create1(EPOLL_CLOEXEC) = 3
pipe2([4, 5], O_CLOEXEC) = 0
epoll_ctl(3, EPOLL_CTL_ADD, 4, {EPOLLIN|EPOLLET, {u32=4, u64=4}}) = 0
mmap(NULL, 8388608, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0) = 0x7fd082ed9000
clone(child_stack=0x7fd0836d8fd8, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID|0x400000, parent_tidptr=0x7fd0836d8fe4, child_tidptr=0x7fd0836d8fe4) = 13547
strace: Process 13547 attached
[pid 13546] write(2, "epoll wait\n", 11epoll wait
<unfinished ...>
[pid 13547] nanosleep({tv_sec=1, tv_nsec=0}, <unfinished ...>
[pid 13546] <... write resumed> ) = 11
[pid 13546] epoll_wait(3, <unfinished ...>
[pid 13547] <... nanosleep resumed> 0x7fd0836d8f20) = 0
[pid 13547] write(2, "close fd\n", 9close fd
) = 9
[pid 13547] close(4) = 0
[pid 13547] exit(0) = ?
[pid 13547] +++ exited with 0 +++
^Cstrace: Process 13546 detached