#include #include #include #include #include #include int parent_to_child_fd[2]; int child_to_parent_fd[2]; #define BASIC_UNIT 1024*1024 //#define BASIC_UNIT 1 char large_buf[BASIC_UNIT]; char huge_buf_r[10*BASIC_UNIT]; char huge_buf_w[10*BASIC_UNIT]; void fd_pair(int *fd) { /* if(pipe(fd)<0) perror("pipe"); */ if(socketpair(AF_UNIX,SOCK_STREAM,0,fd) <0) perror("socketpair"); } void set_nonblocking(int fd) { int val=fcntl(fd,F_GETFL); if(val==-1) perror("fcntl"); val|=O_NONBLOCK; fcntl(fd,F_SETFL,val); } void set_blocking(int fd) { int val=fcntl(fd,F_GETFL); if(val==-1) perror("fcntl"); val&=~O_NONBLOCK; fcntl(fd,F_SETFL,val); } int blocking_write(int fd,const char *buf, size_t len) { int cursor=0; int rc; while(cursor 0){ done_io=1; write_cursor+=rc; if(write_cursor>=sizeof(huge_buf_w)) want_write=0; } else if(errno==EWOULDBLOCK){ write_blocks=1; }else{ printf("child failed writing\n"); break; } } if(want_read && !read_blocks){ rc=read(parent_to_child_fd[0],huge_buf_r+read_cursor,sizeof(huge_buf_r)-read_cursor); if(rc > 0){ done_io=1; read_cursor+=rc; if(read_cursor>=sizeof(huge_buf_r)) want_read=0; } else if(errno==EWOULDBLOCK){ read_blocks=1; }else{ printf("child failed reading\n"); break; } } if(!done_io){ FD_ZERO(&rd); FD_ZERO(&wd); if(read_blocks) FD_SET(parent_to_child_fd[0],&rd); if(write_blocks) FD_SET(child_to_parent_fd[1],&wd); if(select(n,&rd,&wd,NULL,NULL)<0){ printf("child failed select\n"); break; } if(FD_ISSET(parent_to_child_fd[0],&rd)){ printf("child-read ready again\n"); read_blocks=0; } if(FD_ISSET(child_to_parent_fd[1],&wd)){ printf("child-write ready again\n"); write_blocks=0; } } } printf("child done\n"); return 0; } int main(int argc,char *argv[]) { pid_t pid; fd_pair(child_to_parent_fd); fd_pair(parent_to_child_fd); pid = fork(); if(pid<0) perror("fork"); if(pid==0) { close(parent_to_child_fd[1]); close(child_to_parent_fd[0]); set_nonblocking(parent_to_child_fd[0]); set_nonblocking(child_to_parent_fd[1]); do_child(); } else { int status; close(parent_to_child_fd[0]); close(child_to_parent_fd[1]); set_blocking(parent_to_child_fd[1]); set_blocking(child_to_parent_fd[0]); do_parent(); waitpid(pid,&status,0); } }