原文地址:http://www.cnblogs.com/junli/archive/2011/07/07/2099725.html
今天要做这么一件事情,一个主进程fork出N个子进程,然后主进程用roundrobin的策略通知各个子进程, 每通知一次,对应子进程就产生一个线程,去做一件事情。为啥要搞这么麻烦呢,主要是为了防止高并发的情况。其实用线程池应该可以搞定的,不过时间比较赶,能力不济,线程池实现进程来不及。而且一个进程,就算把线程的stack设小,最多也就1000多个线程吧, 多个进程就可以把 capacity 上升到10,000量级。 说穿了,还是为了防止高并发。
今天还学到 open 一个文件,加上 O_APPEND, 就是追加,而且是原子操作,以前我多线程写文件还用了互斥锁,看来完全没有必要。
for (i = 0; i < PROCESS_NUM ; i++)
pid[i] = fork();
我就SB西西的向上面这样写,然后就挂了,问题是出在:当 i =0; fork出第一个子进程,但是循环没结束,所以子进程,会继续fork自己的子进程。 程序就抽风了。
改成下面这样就OK了, 因为fork返回给child process 0,所以用 break 防止child process keep forking .
for(i = 0; i < PROCESS_NUM; i++)
{
if(0 == (pid[i] = fork()))
break; // for child process
}
全部的代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define SIZE 20
#define PROCESS_NUM 10
int main(void)
{
int i;
pid_t pid[PROCESS_NUM];
int fd[PROCESS_NUM][2];
for(i = 0; i < PROCESS_NUM; i++)
{
pid[i] = -1;
pipe(fd[i]);
}
for(i = 0; i < PROCESS_NUM; i++)
{
if(0 == (pid[i] = fork()))
break; // for child process
}
for(i = 0; i < PROCESS_NUM; i++)
{
if(0 == pid[i])
{
close(fd[i][1]);
//child process add here
child(i, fd[i][0]);
return 0;
}
}
//father process
for(i = 0 ; i < PROCESS_NUM; i++)
close(fd[i][0]);
for(i = 0; i < PROCESS_NUM; i++)
notify_child(i, fd[i][1], 'a');
for(i = 0; i < PROCESS_NUM; i++)
notify_child(i, fd[i][1], 'q');
wait(NULL);
return 0;
}
//child 和 notify_child就是简单的管道的读写操作,因为默认read pipe 是阻塞的,所以可以用作消息通知。
void child(int i, int readfd)
{
char flag;
while(1)
{
read(readfd, &flag, 1);
if(flag == 'q')
break;
else
//to do .....
}
}
void notify_child(int i, int writefd, chat flag)
{
write(writefd, &flag, 1);
}