Linux下进程间传递描述符
每个进程都有自己的进程空间,这使得描述符在进程间传递变得不容易。
就比如说Linux下提供进程间传递描述符的机制,但是却要求两个进程是父子进程。
linux进程间传递描述符的机制是通过sendmsg和recvmsg两个函数实现的;
该机制可以传递任意形式的描述符,如pipe、open、mkfifo、socket、accept等;
机制的原理:
1、进程间传递的描述符在内核层面实际上是同一个描述符,只是内核对该描述符的引用标记是+n的,每发送一次,引用次数+1;
//描述符传递给多个进程,但是如果其中一个进程修改了描述符的属性(如socket的同步/异步),那么所有进程的描述符的属性都被改变了;
2、每close一个描述符(发送了多个进程,每个进程都需要close)都会在内核层面对该描述符的引用次数进行-1操作;
需要注意的地方:
1、在使用centos6.5环境下开发的过程中,发现socket描述符传递机制存在一点问题。从父进程发送描述符到子进程接收这个过程中,内核层面描述符的引用次数并没有立即+1。
2、我用父进程异步发送描述符,子进程接受描述符,但是如果父进程做完处理之后,过早close描述符,子进程接收到的描述符仅是一个int型数据,并不是可以使用的描述符。
相关数据结构:
首先的介绍recvmsg和sendmsg的函数调用形式
ssize_t recvmsg(int sockfd, struct msghdr*msg, int flags);
ssize_t sendmsg(int sockfd, struct msghdr*msg, int flags);
msghdr等结构体的定义如下:
struct iovec {
void *iov_base;
size_t iov_len;
}
struct msghdr {
void msg_name;
socklen_t msg_namelen;
struct iovec *msg_iov;
size_t msg_iovlen;
void *msg_control; //用于传递描述符的辅数据
size_t msg_controllen;
int msg_flags;
}
不过需要注意的是,有时候我们仅需要发送描述符,但是我们不能不发送实际数据!可以随便发送一个char当做实际数据;
因为recvmsg和sendmsg的示例代码网上一搜一大把,因此这些代码在这里我就不贴了;