管道原理
int pipe(int pipefd[2]);
- 父进程与子进程的读写是有一定顺序的,当父进程没写入数据时,子进程会在read处等待,所以,父进程写入后,子进程read才会读取数据。
- 当父进程关闭写入的文件描述符,子进程read会接收到信号,读到的字符数为0,依据这个判断结束
简单使用
int main()
{
int pipefd[2];
pipe(pipefd);
pid_t id =fork();
if(id==0)
{
//子进程 ,进行读
close(pipefd[1]);
#define NUM 1024
char buf[NUM];
while(1)
{
memset(buf,0,NUM);
//子进程在等待父进程write
ssize_t s =read(pipefd[0],buf,sizeof(buf)-1);
if(s>0)
{
cout<<buf<<endl;
}
else if(s==0)
{
cout << "父进程写完了,我也退出啦" << endl;
break;
}
}
close(pipefd[0]);
exit(0);
}
else if (id>0)
{
//父进程
close(pipefd[0]);
#define NUM 1024
char ch[NUM]="我是父进程,我在给子进程通过管道传输数据";
for(int i=0;i<5;i++)
{
write(pipefd[1],ch,strlen(ch));
sleep(1);
}
close(pipefd[1]);
id_t res = waitpid(id, nullptr, 0);
if(res > 0)
{
cout << "等待子进程成功" << endl;
}
}
else
{
//错误
cerr<<"创建进程失败\n";
}
return 0;
}
父进程控制子进程
typedef void (*functor)();
void fun1()
{
cout<<"我在写日志"<<endl;
}
void fun2()
{
cout<<"我在处理文件"<<endl;
}
void fun3()
{
cout<<"我在处理数据"<<endl;
}
vector<functor> functors;
void loadFunctor()
{
functors.push_back(fun1);
functors.push_back(fun2);
functors.push_back(fun3);
}
int main()
{
loadFunctor();
int pipefd[2];
//创建管道
pipe(pipefd);
pid_t id =fork();
if(id==0)
{
//子进程,读
close(pipefd[1]);
int missionType =0;
while(1)
{
ssize_t s=read(pipefd[0],&missionType,4);
if(s==0)
{
cout<<"父进程不再分派任务"<<endl;
break;
}
else if(s>0)
{
work(missionType);
}
}
close(pipefd[0]);
exit(0);
}
//父进程
close(pipefd[0]);
int mission=0;
srand( (size_t)time(0));
for(int i=0;i<5;i++)
{
sleep(2);
mission=rand()%functors.size();
write(pipefd[1],&mission,4);
}
close(pipefd[1]);
id_t res = waitpid(id,nullptr,0);
if(res>0)
{
cout<<"父进程等待成功"<<endl;
}
return 0;
}
进程池
typedef void (*functor)();
// int: 进程pid, int: 该进程对应的管道写端fd
typedef pair<int, int> elem;
void fun1()
{
cout<<"我在写日志"<<endl;
}
void fun2()
{
cout<<"我在处理文件"<<endl;
}
void fun3()
{
cout<<"我在处理数据"<<endl;
}
vector<functor> functors;
void loadFunctor()
{
functors.push_back(fun1);
functors.push_back(fun2);
functors.push_back(fun3);
}
void work(int pipefd)
{
while(1)
{
int missionType;
ssize_t s = read(pipefd,&missionType,4);
if(s>0)
{
functors[missionType]();
}
else if(s==0)
{
break;
}
}
}
void sendTask(const vector<elem>& process)
{
srand((size_t) time(0));
for(int i=0;i<5;i++)
{
sleep(1);
//选择哪个子进程
int pick = rand()%5;
//选择执行什么
int task= rand()%3;
cout<<"给编号为:"<<pick<<"的进程派发任务"<<endl;
write(process[pick].second,&task,4);
}
}
// int32_t: 进程pid, int32_t: 该进程对应的管道写端fd
int main()
{
loadFunctor();
vector<elem> process;
int pipefd[2];
for(int i=0;i<5;i++)
{
pipe(pipefd);
pid_t id = fork();
if(id==0)
{
//子进程
close(pipefd[1]);
work(pipefd[0]);
close(pipefd[0]);
cout<<"我是子进程:"<< getpid()<<endl;
exit(0);
}
//父进程做的:
close(pipefd[0]);
elem e(id,pipefd[1]);
process.push_back(e);
}
//父进程,派发任务
sendTask(process);
for(int i=0;i<5;i++)
{
close(process[i].second);
if(waitpid(process[i].first,nullptr,WNOHANG)>0)
{
cout<<"pid :"<<process[i].first<<"等待成功"<<endl;
}
}
return 0;
}