最近在做一个线程池写磁盘文件的任务。主线程通过管道向线程池写任务,线程池从管道的读端读任务。
按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);
}
}