【问题标题】:recvmsg return error(EBADF) when communicate between two processes using socketpair?使用套接字对在两个进程之间进行通信时,recvmsg 返回错误(EBADF)?
【发布时间】:2013-05-15 16:15:34
【问题描述】:

我正在开发一个在两个进程之间进行 IPC 调用的程序。我使用 socketpair 创建了两个套接字 fd:

int fds[2] = {-1,-1};
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) {
    return NULL;
}

在进程A中(具有system权限),我通过send(使用fd[0])函数发送一个整数(句柄):

int sock_send_all(int sock_fd, const uint8_t* buf, int len) {  
    int s = len;
    int ret = send(sock_fd, buf, s, 0);
    ...
}  

在进程B中(有用户权限),等待recvmsg接收句柄(使用fd[1]):

ret = recvmsg(fd, &msg, MSG_NOSIGNAL);  

这里出现问题:recvmsg 立即返回 -1,errorno 等于 9(EBADF)!

我已经上网很长时间试图找到答案,但没有任何有用的信息。你有什么提示或建议吗?谢谢!

这是关于进程权限级别的问题吗?或者我应该使用 setsockopt 来设置一些东西?

【问题讨论】:

  • 进程B是如何获得fd[1]?的
  • @EJP:我实际上是在 Android 平台上开发我的程序。进程B是IBinder(Android IPC机制)的客户端进程。简单来说,fd[1]是通过另一个unix-socket接收的(我认为Android是使用unix-socket在内核中实现IBinder驱动的)
  • 我确认调用 send 和 recvmsg 之前的 fd[0] 和 fd[1] 的值与从socketpair.
  • 请显示用于发送和接收文件描述符的代码。此外,出于特权考虑,您可以在非特权情况下测试代码。你确定你所谓的“系统权限”应用程序真的有吗?仅仅在 Manifest 中声明它不会如此。

标签: android linux sockets ipc


【解决方案1】:

我的问题已经解决了。
关键是将原始文件描述符封装成ParcelFileDescriptor对象,然后将该对象传递给另一个进程,而不是直接在两个进程之间传递文件描述符。
我认为 ParcelFileDescriptor 在android中的实现对原始文件描述符做了一些配置。也许我应该阅读实现代码以找到真正的原因。 谢谢大家!

【讨论】:

  • 我遇到了同样的问题,这也是我的解决方案。 ParcelFileDescriptor 必须作为其包裹在进程间传输,然后在到达另一个进程后重新序列化为 ParcelFileDescriptor。传递原始 int ParcelFileDescriptor.fd 值是不够的。 Unix/Android 可能会为每个进程分配不同的 int fd 值,这些值指向相同的底层管道。
【解决方案2】:

除非我不知道关于 IBinder 的某些内容,否则一个进程中的句柄在另一个进程中无效。为什么不能继续使用原来的socket?

【讨论】:

  • 我正在将一些现有的代码移植到Android中,重写是一项长期而无聊的工作:)
  • 这种交流没有多大意义。首先,像 unix domain socketss 一样,Binder 可以做“魔术”来传递可用的文件描述符,但是在问题的代码中没有证据表明这样做了。回应的评论毫无意义,因为它反对重写,而 Binder 只有在非 Android 代码被重写以使用 Binder 而不是 unix 套接字时才会成为一个因素......
  • @ChrisStratton 同意。整件事对我来说毫无意义。
猜你喜欢
  • 2023-03-07
  • 1970-01-01
  • 1970-01-01
  • 2012-07-06
  • 2011-10-16
  • 2016-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多