免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1692 | 回复: 1
打印 上一主题 下一主题

[C] 这段代码中创建的子进程是如何工作的? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-01-29 16:04 |只看该作者 |倒序浏览
  1. #include <iostream>
  2. #include <sys/socket.h>
  3. #include <sys/epoll.h>
  4. #include <netinet/in.h>
  5. #include <arpa/inet.h>
  6. #include <fcntl.h>
  7. #include <unistd.h>
  8. #include <stdio.h>
  9. #include <errno.h>
  10. #include <sys/types.h>
  11. #include <sys/wait.h>

  12. using namespace std;

  13. #define MAXLINE 5
  14. #define OPEN_MAX 100
  15. #define LISTENQ 20
  16. #define SERV_PORT 5000
  17. #define INFTIM 1000

  18. typedef struct task_t
  19. {
  20.     int fd;
  21.     char buffer[100];
  22.     int n;
  23. }task_t;

  24. int CreateWorker(int nWorker)
  25. {
  26.     if (0 < nWorker)
  27.     {
  28.         bool bIsChild;
  29.         pid_t nPid;

  30.         while (!bIsChild)
  31.         {
  32.             if (0 < nWorker)
  33.             {
  34.                 nPid = ::fork();
  35.                 if (nPid > 0)
  36.                 {
  37.                     bIsChild = false;
  38.                     --nWorker;
  39.                 }
  40.                 else if (0 == nPid)
  41.                 {
  42.                     bIsChild = true;
  43.                     printf("create worker %d success!\n", ::getpid());
  44.                 }
  45.                 else
  46.                 {
  47.                     printf("fork error: %s\n", ::strerror(errno));
  48.                     return -1;
  49.                 }
  50.             }
  51.             else
  52.             {
  53.                 int nStatus;
  54.                 if (-1 == ::wait(&nStatus))
  55.                 {
  56.                     ++nWorker;
  57.                 }
  58.             }
  59.         }
  60.     }

  61.     return 0;
  62. }

  63. void setnonblocking(int sock)
  64. {
  65.     int opts;
  66.     opts=fcntl(sock,F_GETFL);
  67.     if(opts<0)
  68.     {
  69.         perror("fcntl(sock,GETFL)");
  70.         exit(1);
  71.     }
  72.     opts = opts|O_NONBLOCK;
  73.     if(fcntl(sock,F_SETFL,opts)<0)
  74.     {
  75.         perror("fcntl(sock,SETFL,opts)");
  76.         exit(1);
  77.     }   
  78. }

  79. int main()
  80. {
  81.     int i, maxi, listenfd, connfd, sockfd,epfd,nfds;
  82.     ssize_t n;
  83.     char line[MAXLINE];
  84.     socklen_t clilen;
  85.     struct epoll_event ev,events[20];

  86.     struct sockaddr_in clientaddr;
  87.     struct sockaddr_in serveraddr;
  88.     listenfd = socket(AF_INET, SOCK_STREAM, 0);
  89.        bzero(&serveraddr, sizeof(serveraddr));
  90.     serveraddr.sin_family = AF_INET;
  91.     char *local_addr="127.0.0.1";
  92.     inet_aton(local_addr,&(serveraddr.sin_addr));//htons(SERV_PORT);
  93.     serveraddr.sin_port=htons(SERV_PORT);
  94.       // 地址重用
  95.     int nOptVal = 1;
  96.     socklen_t nOptLen = sizeof(int);
  97.     if (-1 == ::setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &nOptVal, nOptLen))
  98.     {
  99.         return -1;
  100.     }   
  101.     setnonblocking(listenfd);
  102.     bind(listenfd,(sockaddr *)&serveraddr, sizeof(serveraddr));
  103.     listen(listenfd, LISTENQ);   
  104.    
  105.     CreateWorker(5);
  106.    
  107.     //把socket设置为非阻塞方式
  108.    
  109.     //生成用于处理accept的epoll专用的文件描述符
  110.     epfd=epoll_create(256);   
  111.     //设置与要处理的事件相关的文件描述符
  112.     ev.data.fd=listenfd;
  113.     //设置要处理的事件类型
  114.     ev.events=EPOLLIN|EPOLLET;
  115.     //ev.events=EPOLLIN;
  116.     //注册epoll事件
  117.     epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);

  118.      //CreateWorker(5);
  119.      
  120.     maxi = 0;
  121.    
  122.     task_t task;
  123.     task_t *ptask;
  124.     while(true)
  125.     {
  126.         //等待epoll事件的发生
  127.         nfds=epoll_wait(epfd,events,20,500);
  128.         //处理所发生的所有事件     
  129.         for(i=0;i<nfds;++i)
  130.         {
  131.             if(events[i].data.fd==listenfd)
  132.             {               
  133.                 connfd = accept(listenfd,NULL, NULL);
  134.                 if(connfd<0){                    
  135.                     printf("connfd<0, listenfd = %d\n", listenfd);
  136.                     printf("error = %s\n", strerror(errno));
  137.                     exit(1);
  138.                 }
  139.                 setnonblocking(connfd);
  140.                
  141.                 //设置用于读操作的文件描述符
  142.                 memset(&task, 0, sizeof(task));
  143.                 task.fd = connfd;
  144.                 ev.data.ptr = &task;
  145.                 //设置用于注册的读操作事件
  146.                 ev.events=EPOLLIN|EPOLLET;
  147.                 //ev.events=EPOLLIN;
  148.                 //注册ev
  149.                 epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);
  150.             }
  151.             else if(events[i].events&EPOLLIN)
  152.             {
  153.                 cout << "EPOLLIN" << endl;
  154.                 ptask = (task_t*)events[i].data.ptr;
  155.                 sockfd = ptask->fd;
  156.                
  157.                 if ( (ptask->n = read(sockfd, ptask->buffer, 100)) < 0) {
  158.                     if (errno == ECONNRESET) {
  159.                         close(sockfd);
  160.                         events[i].data.ptr = NULL;
  161.                     } else
  162.                         std::cout<<"readline error"<<std::endl;
  163.                 } else if (ptask->n == 0) {
  164.                     close(sockfd);
  165.                     events[i].data.ptr = NULL;
  166.                 }
  167.                 ptask->buffer[ptask->n] = '\0';
  168.                 cout << "read " << ptask->buffer << endl;
  169.                
  170.                 //设置用于写操作的文件描述符                                
  171.                 ev.data.ptr = ptask;
  172.                 //设置用于注测的写操作事件
  173.                 ev.events=EPOLLOUT|EPOLLET;
  174.                                 
  175.                 //修改sockfd上要处理的事件为EPOLLOUT
  176.                 epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
  177.             }
  178.             else if(events[i].events&EPOLLOUT)
  179.             {   
  180.                 cout << "EPOLLOUT" << endl;
  181.                 ptask = (task_t*)events[i].data.ptr;
  182.                 sockfd = ptask->fd;
  183.                
  184.                 write(sockfd, ptask->buffer, ptask->n);
  185.                
  186.                 //设置用于读操作的文件描述符              
  187.                 ev.data.ptr = ptask;
  188.                
  189.                 //修改sockfd上要处理的事件为EPOLIN
  190.                 epoll_ctl(epfd,EPOLL_CTL_DEL,sockfd,&ev);
  191.                 cout << "write " << ptask->buffer;
  192.                 memset(ptask, 0, sizeof(*ptask));
  193.                 close(sockfd);
  194.             }
  195.         }
  196.     }
  197.     return 0;
  198. }
复制代码

论坛徽章:
0
2 [报告]
发表于 2009-01-29 16:06 |只看该作者
CreateWorker后5个子进程处理Epoll?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP