unix 域套接字的边缘触发 epoll
edge triggered epoll for unix domain socket
当 epoll_wait
在边缘触发模式下阻塞 unix 域套接字上的 EPOLLOUT
事件时,我遇到了一个奇怪的问题。
一些细节:我在两个进程之间使用 boost ASIO
IPC,文件描述符传递。
以下是一些 strace 日志:
25097 16:59:04.273555 epoll_ctl(4, EPOLL_CTL_MOD, 37, {EPOLLIN|EPOLLPRI|EPOLLOUT|EPOLLERR|EPOLLHUP|EPOLLET, {u32=40872176, u64=40872176}}) = 0
25097 16:59:04.273588 epoll_wait(4, {{EPOLLOUT, {u32=40872176, u64=40872176}}}, 128, -1) = 1
25097 16:59:04.273617 sendmsg(37, {msg_name(0)=NULL, msg_iov(1)=[{data skipped, 247}], msg_controllen=24, {cmsg_len=24, cmsg_level=SOL_SOCKET, cmsg_type=SCM_RIGHTS, {34, 49}}, msg_flags=0}, MSG_NOSIGNAL) = 247
25097 16:59:04.273671 epoll_ctl(4, EPOLL_CTL_DEL, 34, {0, {u32=0, u64=0}}) = 0
25097 16:59:04.273715 close(34) = 0
25097 16:59:04.273752 close(49) = 0
25097 16:59:04.273801 epoll_wait(4, {{EPOLLOUT, {u32=40872176, u64=40872176}}}, 128, -1) = 1
25097 16:59:04.273848 epoll_wait(4, <unfinished ...>
我在上次 epoll_wait
通话中被屏蔽了。
我的理解是,当我使用边沿触发模式 (EPOLLET
) 时,如果 fd 已经准备好进行写操作,我肯定会阻塞。
问题是:如果unix domain socket准备好写入操作,如何调试? /proc/net/unix
没有显示任何有趣的内容。
My understanding is that as I'm using edge triggered mode (EPOLLET
),
then I'm for sure can block if fd is already ready for write
operations.
同意。
The question is: how to debug if unix domain socket is ready for write
operations?
如果你有一个带有调试符号的内核文件,你可以这样做
gdb vmlinux /proc/kcore
以及 /proc/net/unix
的 Num
列中的 struct sock
地址
p ((struct sock *)0xaddress)->sk_wmem_alloc
- 检查已提交的传输队列字节和其他结构元素,以查看套接字的发送缓冲区是否还有 space 剩余。
但实际上您不需要这样做,因为 strace 输出已经在倒数第二行显示 EPOLLOUT
事件,并且在该事件和最后一行的 epoll_wait
之间有没有可以改变情况的系统调用,我。 e.没有信号边缘。我认为在这里等待边缘触发是不明智的。
当 epoll_wait
在边缘触发模式下阻塞 unix 域套接字上的 EPOLLOUT
事件时,我遇到了一个奇怪的问题。
一些细节:我在两个进程之间使用 boost ASIO
IPC,文件描述符传递。
以下是一些 strace 日志:
25097 16:59:04.273555 epoll_ctl(4, EPOLL_CTL_MOD, 37, {EPOLLIN|EPOLLPRI|EPOLLOUT|EPOLLERR|EPOLLHUP|EPOLLET, {u32=40872176, u64=40872176}}) = 0
25097 16:59:04.273588 epoll_wait(4, {{EPOLLOUT, {u32=40872176, u64=40872176}}}, 128, -1) = 1
25097 16:59:04.273617 sendmsg(37, {msg_name(0)=NULL, msg_iov(1)=[{data skipped, 247}], msg_controllen=24, {cmsg_len=24, cmsg_level=SOL_SOCKET, cmsg_type=SCM_RIGHTS, {34, 49}}, msg_flags=0}, MSG_NOSIGNAL) = 247
25097 16:59:04.273671 epoll_ctl(4, EPOLL_CTL_DEL, 34, {0, {u32=0, u64=0}}) = 0
25097 16:59:04.273715 close(34) = 0
25097 16:59:04.273752 close(49) = 0
25097 16:59:04.273801 epoll_wait(4, {{EPOLLOUT, {u32=40872176, u64=40872176}}}, 128, -1) = 1
25097 16:59:04.273848 epoll_wait(4, <unfinished ...>
我在上次 epoll_wait
通话中被屏蔽了。
我的理解是,当我使用边沿触发模式 (EPOLLET
) 时,如果 fd 已经准备好进行写操作,我肯定会阻塞。
问题是:如果unix domain socket准备好写入操作,如何调试? /proc/net/unix
没有显示任何有趣的内容。
My understanding is that as I'm using edge triggered mode (
EPOLLET
), then I'm for sure can block if fd is already ready for write operations.
同意。
The question is: how to debug if unix domain socket is ready for write operations?
如果你有一个带有调试符号的内核文件,你可以这样做
gdb vmlinux /proc/kcore
以及 /proc/net/unix
Num
列中的 struct sock
地址
p ((struct sock *)0xaddress)->sk_wmem_alloc
- 检查已提交的传输队列字节和其他结构元素,以查看套接字的发送缓冲区是否还有 space 剩余。
但实际上您不需要这样做,因为 strace 输出已经在倒数第二行显示 EPOLLOUT
事件,并且在该事件和最后一行的 epoll_wait
之间有没有可以改变情况的系统调用,我。 e.没有信号边缘。我认为在这里等待边缘触发是不明智的。