管道一直是进程间的通讯的重要方式。
首先我要说一下进程通讯之间为什么会需要管道,因为进程之间的内存是独立的,我为什么这么说呢,好多人都只知道fork却不知道所以然,众所周知,fork之后会出现子进程,但是我就问你是否考虑过父子进程的内存关系,其实fork中的子进程是对fork之前的主进程的内存的一个复制,然后,拼接到pid==0的内存,形成一个内存空间,好如果我们在for循环里循环4个子进程,那么每一个子进程的内存绝对都是独立的,我们没有办法去达到进程的内存公用,我们这里有几个方案,共享内存(或者以mmap实现共享内存),或者使用消息队列,信号量或者使用管道进行通讯,传递一些比较重要的东西,比如说文件描述符这一类的东西,所以我们在进程通讯的时候要使用管道
但是在读写中会产生阻塞,对于许多异步程序会产生很严重的影响,为此我们需要把管道设置为非阻塞的 在之前我学习管道的思路一直是pipe创建完管道后直接fork出现子进程,然后父进程这里在用管道读,子进程用管道写,但是问题就是会出现阻塞!但是linux c中可以用poll来解决,由于只有两个文件描述符读和写所以我们完全没有必要去使用epoll做边缘触发,直接使用poll做轮循就可以,毕竟只有2个文件描述符嘛
c语言中我们可以采用poll来解决这个问题
int poll(struct pollfd *fds,nfds_t nfds, int timeout);
设置完成超时时间后我们可以很快中断操作,避免发生阻塞使程序继续执行,由于我写的是python所以也可以这么处理
import os
import select
class WorkPipe:
read = None
write = None
READ_ONLY = select.POLLIN
READ_WRITE = select.POLLOUT
#create pipe
def createWorker_pipe(self):
r,w = os.pipe()
self.read = r
self.write = w
pass
#write pipe
def readWorker_pipe(self):
# os.close(self.write)
if(self.pipe_wait(self.read,self.READ_ONLY) == True):
pipeOpenHandel = os.fdopen(self.read)
readContent = pipeOpenHandel.read()
return readContent
pass
return ""
pass
#write pipe
def writeWorker_pipe(self,socketfd):
# os.close(self.read)
if (self.pipe_wait(self.write, self.READ_WRITE) == True):
pipeWriteHandel = os.fdopen(self.write, 'w')
pipeWriteHandel.write(str(socketfd) + "&")
return True
pass
return False
pass
def pipe_wait(self,fd,type):
poller = select.poll()
poller.register(fd, type)
result = poller.poll(1)
if(len(result) > 0):
return True
else:
return False
pass
pass
但是由于是非阻塞的所以我不主张关闭文件描述符,关闭文件描述符程序可能在轮循中报错