最近在做一个线程池写磁盘文件的任务。主线程通过管道向线程池写任务,线程池从管道的读端读任务。
按UNIX环境高级编程说的,我在主线程中关闭了管道的读端,在线程池的初始化时关闭了写端。
但是,在这种情况下,没法正常工作,只有在不关闭管道的读和写端的时候才能正常工作。
原来书上讲的是在进程的情况下,而不是我所用的线程,子线程是和创建它的进程共享fd的,任何一方关闭管道的读或写都会影响到另一方。
还有一个问题需要说明的是,管道(阻塞的读和写)写满之后,会阻塞到写端;
只有读端把管道读空(我的机器上的管道长度是4K)之后才能继续写管道,我以前以为是,只要读端读了一个字节,写端就可以继续写。
还有是:我一开始疯狂的写管道,可以写64K而不是机器上的标识(我用ulimit -p查看到是4K)4K。这个我也不知道是怎么回事儿。
代码如下:
#include "my.h" void * listen_thread(void *arg); static void sig_usr(int signo); static void sig_pipe(int signo); int pipe_fd_work[2]; int main(int argc, char** argv) { if (pipe(pipe_fd_work) < 0) { cerr<<"open pipe_fd_work error:"<<strerror(errno)<<endl; return -1; } else { //if i close this read of pipe ,thread can't read it //because they share the same fd //close(pipe_fd_work[0]); } signal(SIGINT, sig_usr); pthread_t listen_pid; pthread_create(&listen_pid, NULL, listen_thread, NULL); int nwrited; char *writebuf = new char[1024]; setnonblock(pipe_fd_work[1]); while(1) { cout<<"before write\n"<<endl; nwrited = write(pipe_fd_work[1], writebuf, 1024); cout<<"after write\n"<<endl; if (nwrited == -1) { cerr<<"write pipe error:"<<strerror(errno)<<endl; } else { cout<<"writen:"<<nwrited<<endl; } } pthread_join(listen_pid, NULL); return 0; } void * listen_thread(void *arg) { char *buf = new char[2048]; int nreaded; while(1) { nreaded = read(pipe_fd_work[0], buf, 2048); if (nreaded == -1) break; else { cout<<"readed:"<<nreaded<<endl; } sleep(10); } delete [] buf; buf = NULL; signal(SIGPIPE, sig_pipe); } static void sig_pipe(int signo) { if (signo == SIGPIPE) { cout<<"progrom exit"<<endl; exit(1); } } static void sig_usr(int signo) { if (signo == SIGINT) { cout<<"progrom exit"<<endl; exit(1); } }