int socketpair(int domain, int type, int protocol, int sockfd[2]); //创建未命名的全双工管道
domain只能为AF_UNIX,也就是限制在本地使用
type可以是SOCK_STREAM或SOCK_DGRAM,SOCK_STREAM相当于创建了双向流管道,管道的每一端都可以write或read,并且两端的数据流对流是分开的
protocol必须是0
sockfd数组返回管道两端的socket描述符
在2.6.27的内核版本后,type支持了SOCK_CLOEXEC(close on exec )和SOCK_NONBLOCK(非阻塞系统描述符)标志,以节省fcntl系统调用
socketpair创建的描述符常用于亲缘进程间通信,如父进程调用了socketpair后,父进程再调用fork出子进程,子进程自动继承了描述符(前提是没有close on exec),那么父子进程就可以用sockfd进行通信。
例子,父进程在sockepair后,再fork出子进程,然后:
#include<sys/types.h> #include<sys/wait.h> #include<sys/socket.h> #include<unistd.h> #include<iostream> #include<cstring> using namespace std; int main(){ int fd[2]; if(socketpair(AF_UNIX,SOCK_STREAM,0,fd)<0)//父进程调用socketpair创建fd数组 cout<<"socketpair error"<<endl; pid_t pid; if((pid=fork())<0) cout<<"fork error"<<endl; else if(pid==0){ close(fd[0]);//父进程持有fd[0]端,子进程持有fd[1]端 write(fd[1],"hello parent",strlen("hello parent"));//子进程通过fd[1]向父进程发送消息 char buf[20]; while(read(fd[1],buf,20)==-1);//子进程在fd[1]端等待父进程的消息 buf[13]=‘\0‘; cout<<"child receive: "<<buf<<endl; } else{ close(fd[1]); write(fd[0],"hello child",strlen("hello world"));//父进程通过fd[0]端向子进程发送消息 char buf[20]; while(read(fd[0],buf,20)==-1);//父进程在fd[0]端等待子进程的消息 cout<<"parent receive: "<<buf<<endl; wait(NULL); } return 0; }
程序输出:
parent receive: hello parent
child receive: hello child
可见socketpair创建的UNIX域套接字可用于亲缘进程间通信(未命名限制了只能在亲缘进程间使用),在nginx中,master进程就利用socketpair创建套接字然后fork出worker进程,这样master进程和worker进程间就可以利用socketpair产生的套接字通信了。
原文:http://blog.csdn.net/liuxuejiang158blog/article/details/26154893