读Nginx源码,看到了socketpair函数,以前没有见过,网上找到一篇博客介绍的很详细,这里转载过来。
http://liulixiaoyao.blog.51cto.com/1361095/533469/
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <error.h>
- #include <errno.h>
- #include <sys/socket.h>
- #include <stdlib.h>
- #define BUF_SIZE 30
- int main(){
- int s[2];
- int w,r;
- char * string = "This is a test string";
- char * buf = (char*)calloc(1 , BUF_SIZE);
- if( socketpair(AF_UNIX,SOCK_STREAM,0,s) == -1 ){
- printf("create unnamed socket pair failed:%s\n",strerror(errno) );
- exit(-1);
- }
- /*******test in a single process ********/
- if( ( w = write(s[0] , string , strlen(string) ) ) == -1 ){
- printf("Write socket error:%s\n",strerror(errno));
- exit(-1);
- }
- /*****read*******/
- if( (r = read(s[1], buf , BUF_SIZE )) == -1){
- printf("Read from socket error:%s\n",strerror(errno) );
- exit(-1);
- }
- printf("Read string in same process : %s \n",buf);
- if( (r = read(s[0], buf , BUF_SIZE )) == -1){
- printf("Read from socket s0 error:%s\n",strerror(errno) );
- exit(-1);
- }
- printf("Read from s0 :%s\n",buf);
- printf("Test successed\n");
- exit(0);
- }
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <error.h>
- #include <errno.h>
- #include <sys/socket.h>
- #include <stdlib.h>
- #define BUF_SIZE 30
- int main(){
- int s[2];
- int w,r;
- char * string = "This is a test string";
- char * buf = (char*)calloc(1 , BUF_SIZE);
- pid_t pid;
- if( socketpair(AF_UNIX,SOCK_STREAM,0,s) == -1 ){
- printf("create unnamed socket pair failed:%s\n",strerror(errno) );
- exit(-1);
- }
- /***********Test : fork but don't close any fd in neither parent nor child process***********/
- if( ( pid = fork() ) > 0 ){
- printf("Parent process's pid is %d\n",getpid());
- close(s[1]);
- if( ( w = write(s[0] , string , strlen(string) ) ) == -1 ){
- printf("Write socket error:%s\n",strerror(errno));
- exit(-1);
- }
- }else if(pid == 0){
- printf("Fork child process successed\n");
- printf("Child process's pid is :%d\n",getpid());
- close(s[0]);
- }else{
- printf("Fork failed:%s\n",strerror(errno));
- exit(-1);
- }
- /*****read***In parent and child****/
- if( (r = read(s[1], buf , BUF_SIZE )) == -1){
- printf("Pid %d read from socket error:%s\n",getpid() , strerror(errno) );
- exit(-1);
- }
- printf("Pid %d read string in same process : %s \n",getpid(),buf);
- printf("Test successed , %d\n",getpid());
- exit(0);
- }
原因是:如果子进程先sleep,父进程读取完数据之后,父进程退出,此时写端s[0]的引用计数变为0(之前子进程已主动close了一次),被系统释放,根据read的语义,当子进程被唤醒后会读取到EOF;但是当我们先让父进程sleep的时候,子进程读取完后退出,由于写端在父进程,没有被释放,所以父进程此时阻塞在读操作上.