Tilera多线程网络编程总结

http://blog.csdn.net/zwleagle/article/details/8851400

http://blog.sina.com.cn/s/blog_a574f78401015v2o.html

http://www.dssz.com/1341360.html

http://www.dssz.com/1341355.html


多线程网络处理服务器demo

  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <errno.h>  
  4. #include <string.h>  
  5. #include <sys/types.h>  
  6. #include <netinet/in.h>  
  7. #include <sys/socket.h>  
  8. #include <sys/wait.h>  
  9. #include <unistd.h>  
  10. #include <arpa/inet.h>  
  11. //#include <openssl/ssl.h>  
  12. //#include <openssl/err.h>  
  13. #include <fcntl.h>  
  14. #include <sys/epoll.h>  
  15. #include <sys/time.h>  
  16. #include <sys/resource.h>  
  17. #include <pthread.h>  
  18. #include <assert.h>  
  19.   
  20. //#define DEBUG_TILERA  
  21.   
  22.   
  23. #ifdef DEBUG_TILERA  
  24. #include <tmc/alloc.h>  
  25.   
  26. #include <arch/cycle.h>  
  27. #include <arch/spr.h>  
  28.   
  29. #include <tmc/cpus.h>  
  30. #include <tmc/sync.h>  
  31. #include <tmc/task.h>  
  32. #endif  
  33.   
  34. /* These are non-NULL pointers that will result in page faults 
  35. * under normal circumstances, used to verify that nobody uses 
  36. * non-initialized list entries. 
  37. */  
  38.   
  39.   
  40. #define MAXBUF 1024  
  41. #define MAXEPOLLSIZE 500000  
  42.   
  43. #define MAX_THREAD_NUMBER 200  
  44. int  THREAD_NUMBER = 50;  
  45.   
  46.   
  47. int kdpfd;  
  48. struct epoll_event events[MAXEPOLLSIZE];  
  49.   
  50. struct epoll_event thread_events[MAX_THREAD_NUMBER][MAXEPOLLSIZE];  
  51. int fdpool[MAX_THREAD_NUMBER] = {-1};  
  52.   
  53. pthread_t  handle_receive_thrdid[MAX_THREAD_NUMBER];  
  54.   
  55.   
  56. int msgcount = 0;  
  57. int timecount = 0;  
  58.   
  59. int count_packet= 0;  
  60.   
  61. pthread_mutex_t connet_count_lock = PTHREAD_MUTEX_INITIALIZER;  
  62. int connect_count = 0;  
  63.   
  64. pthread_mutex_t curfds_lock;  
  65. int curfds;  
  66.   
  67. char buffer[MAX_THREAD_NUMBER][MAXBUF + 1];  
  68. pthread_t thread_count;  
  69.   
  70.   
  71. cpu_set_t cpus;  
  72.   
  73.   
  74.   
  75. void BubbleSort(unsigned char R[],int n)  
  76. {  
  77.     int i,j;  
  78.     unsigned char temp;  
  79.     for (i=0; i<n-1; i++ )  
  80.     {  
  81.         for (j=n-2; j>=i; j--)  
  82.         {  
  83.             if (R[j]>R[j+1])  
  84.             {  
  85.                 temp=R[j];  
  86.                 R[j]=R[j+1];  
  87.                 R[j+1]=temp;  
  88.             }  
  89.         }  
  90.     }  
  91. }  
  92.   
  93. /* 
  94. setnonblocking - 设置句柄为非阻塞方式 
  95. */  
  96. int setnonblocking(int sockfd)  
  97. {  
  98.     if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1)  
  99.     {  
  100.         return -1;  
  101.     }  
  102.     return 0;  
  103. }  
  104.   
  105. /* 
  106. handle_message - 处理每个 socket 上的消息收发 
  107. */  
  108.   
  109.   
  110.   
  111. static void *handle_count(void* arg)  
  112. {  
  113.     int precount, speed;  
  114.   
  115.     while(1)  
  116.     {  
  117.         precount = msgcount;  
  118.         sleep(5);  
  119.         timecount += 5;  
  120.         //printf("The tcp connection count is %d\n",count_tcp);  
  121.         //printf("The received packets count is %d, time %d\n",msgcount, timecount);  
  122.         speed = msgcount - precount ;  
  123.         printf("The received speed  is %d/5seconds, connect %d, tatol packets %d\n",speed, connect_count, msgcount);  
  124.     }  
  125.   
  126.     return NULL;  
  127. }  
  128.   
  129. static void * handl_receive_msg(void * arg)  
  130. {  
  131.     int fdind = 0;  
  132.     int nfds = 0;  
  133.     int len;  
  134.     struct epoll_event ev;  
  135.     int fdi;  
  136.   
  137.     char* buf ;  
  138.   
  139.     fdind = (int)arg;  
  140.   
  141.     buf = (char*)&buffer[fdind];  
  142.   
  143.     // printf("fd... %d \n", fdind);  
  144.   
  145.     while(1)  
  146.     {  
  147.         nfds = epoll_wait(fdpool[fdind], &thread_events[fdind][0], MAXEPOLLSIZE, -1);  
  148.         if (nfds == -1)  
  149.         {  
  150.             perror("epoll_wait");  
  151.             break;  
  152.         }  
  153.   
  154.         for( fdi = 0; fdi < nfds; fdi++)  
  155.         {  
  156.             if((thread_events[fdind][fdi].events & EPOLLIN)  
  157.                /*&&(!(thread_events[fdind][fdi].events & EPOLLRDHUP))*/)  
  158.             {  
  159.                 while((-1 != (len = recv(thread_events[fdind][fdi].data.fd, buf, MAXBUF, 0)))  
  160.                       ||((-1 == len) && (EAGAIN != errno)))  
  161.                 {  
  162.                     //perror("recv error ");  
  163.                     //printf("recv error %d  fd %d\n", errno, thread_events[fdind][fdi].data.fd);  
  164.                     //goto next;  
  165.   
  166.   
  167.                     if (len > 0)  
  168.                     {  
  169.   
  170.                         /*printf 
  171.                         ("%d receive message success   total %d bytes data  msgcount %d\n", 
  172.                          new_fd,   len, msgcount);*/  
  173.                         msgcount++;  
  174.                         BubbleSort(buf ,len);  
  175.                     }  
  176.                     else if(len == 0)  
  177.                     {  
  178.                         //printf("the socket %d is closed \n", new_fd);  
  179.                         epoll_ctl(fdpool[fdind], EPOLL_CTL_DEL, thread_events[fdind][fdi].data.fd,&ev);  
  180.                         close(thread_events[fdind][fdi].data.fd);  
  181.                         pthread_mutex_lock(&connet_count_lock);  
  182.                         connect_count--;  
  183.                         pthread_mutex_unlock (&connet_count_lock);  
  184.   
  185.                         break;  
  186.                     }  
  187.                     else  
  188.                     {  
  189.   
  190.                         printf(" socket %d receive message fail error code: %d,  error message: '%s'\n",  
  191.                                thread_events[fdind][fdi].events, errno, strerror(errno));  
  192.   
  193.   
  194.                         epoll_ctl(fdpool[fdind], EPOLL_CTL_DEL, thread_events[fdind][fdi].data.fd,&ev);  
  195.                         close(thread_events[fdind][fdi].data.fd);  
  196.                         pthread_mutex_lock(&connet_count_lock);  
  197.                         connect_count--;  
  198.                         pthread_mutex_unlock (&connet_count_lock);  
  199.   
  200.   
  201.                         //pthread_mutex_lock (&(curfds_lock));  
  202.                         //curfds--;  
  203.                         //pthread_mutex_unlock (&(curfds_lock));  
  204.                         break;  
  205.                     }  
  206.   
  207.                 }  
  208.             }  
  209.             /* else if((thread_events[fdind][fdi].events & EPOLLRDHUP)) 
  210.              { 
  211.                  epoll_ctl(fdpool[fdind], EPOLL_CTL_DEL, thread_events[fdind][fdi].data.fd,&ev); 
  212.                  close(thread_events[fdind][fdi].data.fd); 
  213.                  pthread_mutex_lock(&connet_count_lock); 
  214.                  connect_count--; 
  215.                  pthread_mutex_unlock (&connet_count_lock); 
  216.  
  217.                  printf("event.... %x \n", thread_events[fdind][fdi].events); 
  218.  
  219.              }*/  
  220.             else  
  221.             {  
  222.                 printf("other event %u\n",thread_events[fdind][fdi].events );  
  223.             }  
  224.   
  225.   
  226.         }  
  227.     }  
  228.   
  229.     return NULL;  
  230.   
  231. }  
  232.   
  233.   
  234.   
  235. int fd_index = 0;  
  236.   
  237. int main(int argc, char **argv)  
  238. {  
  239.     int listener, new_fd,  nfds, n, ret;  
  240.     socklen_t len;  
  241.     struct sockaddr_in my_addr, their_addr;  
  242.     unsigned int myport, lisnum;  
  243.     struct epoll_event ev;  
  244.     struct rlimit rt;  
  245.     int    fdind;  
  246.     int   ind ;  
  247.   
  248.     if(5 != argc)  
  249.     {  
  250.   
  251.         printf("Usage: %s <thread_number(0 ~ 200)> <port(0-65535)> <listen queue number>  <IP Address>   \n", argv[0]);  
  252.         exit(1);  
  253.   
  254.     }  
  255.   
  256.     if(argv[1])  
  257.         THREAD_NUMBER = atoi(argv[1]);  
  258.   
  259.     if (argv[2])  
  260.         myport = atoi(argv[2]);  
  261.     else  
  262.         myport = 7838;  
  263.   
  264.     if (argv[3])  
  265.         lisnum = atoi(argv[3]);  
  266.     else  
  267.         lisnum = 2;  
  268.   
  269.   
  270.   
  271. #ifdef DEBUG_TILERA  
  272.     if (tmc_cpus_get_my_affinity(&cpus) != 0)  
  273.     {  
  274.         printf("tmc_cpus_get_my_affinity() failed.\n");  
  275.         tmc_task_die("tmc_cpus_get_my_affinity() failed.");  
  276.     }  
  277.     if (tmc_cpus_count(&cpus) < MAX_THREAD)  
  278.     {  
  279.         printf("\nInsufficient cpus available.\n");  
  280.         tmc_task_die("Insufficient cpus available.");  
  281.     }  
  282. #endif  
  283.   
  284.   
  285.     pthread_mutex_init (&connet_count_lock, NULL);  
  286.     pthread_mutex_init (&(curfds_lock), NULL);  
  287.   
  288.     for( ind = 0; ind < THREAD_NUMBER; ind++ )  
  289.     {  
  290.   
  291.         fdpool[ind] = epoll_create(MAXEPOLLSIZE);  
  292.   
  293.     }  
  294.   
  295.     for( ind = 0; ind < THREAD_NUMBER; ind++)  
  296.     {  
  297.         pthread_create(&handle_receive_thrdid[ind], NULL, &handl_receive_msg, (void*)ind);  
  298.     }  
  299.   
  300.     if (pthread_create(&thread_count, NULL, &handle_count, NULL) != 0)  
  301.     {  
  302. #ifdef DEBUG_TILERA  
  303.         tmc_task_die("pthread_create() failed.");  
  304. #endif  
  305.     }  
  306.   
  307.     /* 设置每个进程允许打开的最大文件数 */  
  308.     rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE;  
  309.     if (setrlimit(RLIMIT_NOFILE, &rt) == -1)  
  310.     {  
  311.         perror("setrlimit");  
  312.         exit(1);  
  313.     }  
  314.     else printf("set the system resource success!\n");  
  315.   
  316.     /* 开启 socket 监听 */  
  317.     if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1)  
  318.     {  
  319.         perror("socket");  
  320.         exit(1);  
  321.     }  
  322.     else  
  323.         printf("socket create success!n");  
  324.   
  325.     setnonblocking(listener);  
  326.   
  327.     bzero(&my_addr, sizeof(my_addr));  
  328.     my_addr.sin_family = PF_INET;  
  329.     my_addr.sin_port = htons(myport);  
  330.     if (argv[4])  
  331.         my_addr.sin_addr.s_addr = inet_addr(argv[4]);  
  332.     else  
  333.         my_addr.sin_addr.s_addr = INADDR_ANY;  
  334.   
  335.     if (bind  
  336.         (listener, (struct sockaddr *) &my_addr, sizeof(struct sockaddr))  
  337.         == -1)  
  338.     {  
  339.         perror("bind");  
  340.         exit(1);  
  341.     }  
  342.     else  
  343.         printf("IP address and port bing success!\n");  
  344.   
  345.     if (listen(listener, lisnum) == -1)  
  346.     {  
  347.         perror("listen");  
  348.         exit(1);  
  349.     }  
  350.     else  
  351.         printf("start to work!\n");  
  352.   
  353.   
  354.   
  355.   
  356.   
  357.     /* 创建 epoll 句柄,把监听 socket 加入到 epoll 集合里 */  
  358.     kdpfd = epoll_create(MAXEPOLLSIZE);  
  359.     len = sizeof(struct sockaddr_in);  
  360.     ev.events = EPOLLIN;  
  361.     ev.data.fd = listener;  
  362.     if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, listener, &ev) < 0)  
  363.     {  
  364.         fprintf(stderr, "epoll set insertion error: fd=%d\n", listener);  
  365.         return -1;  
  366.     }  
  367.     else  
  368.         printf("listen socket add to epoll success\n");  
  369.   
  370.   
  371.   
  372.   
  373.     curfds = 1;  
  374.     while (1)  
  375.     {  
  376.         /* 等待有事件发生 */  
  377.         nfds = epoll_wait(kdpfd, events, MAXEPOLLSIZE, -1);  
  378.         if (nfds == -1)  
  379.         {  
  380.             perror("epoll_wait");  
  381.             break;  
  382.         }  
  383.         /* 处理所有事件 */  
  384.         for (n = 0; n < nfds; ++n)  
  385.         {  
  386.             // printf("The number of fd %d \n", nfds);  
  387.             if (events[n].data.fd == listener)  
  388.             {  
  389.                 new_fd = accept(listener, (struct sockaddr *) &their_addr,  
  390.                                 &len);  
  391.                 if (new_fd < 0)  
  392.                 {  
  393.                     perror("accept");  
  394.                     continue;  
  395.                 }  
  396.                 //else  
  397.                 // printf("connect from  %x:%x, allocate socket for %x\n", inet_ntoa(their_addr.sin_addr), ntohs(their_addr.sin_port), new_fd);  
  398.                 pthread_mutex_lock(&connet_count_lock);  
  399.                 connect_count++;  
  400.                 pthread_mutex_unlock (&connet_count_lock);  
  401.                 setnonblocking(new_fd);  
  402.                 ev.events = EPOLLIN | EPOLLET;  
  403.                 ev.data.fd = new_fd;  
  404.   
  405.                 fdind = fd_index % THREAD_NUMBER;  
  406.   
  407.                 if (epoll_ctl(fdpool[fdind], EPOLL_CTL_ADD, new_fd, &ev) < 0)  
  408.                 {  
  409.                     fprintf(stderr, "add socket '%d' to epoll fail %s\n",  
  410.                             new_fd, strerror(errno));  
  411.                     // pool_destroy ();  
  412.   
  413.                     return -1;  
  414.                 }  
  415.   
  416.                 fd_index++;  
  417.                 //pthread_mutex_lock (&(curfds_lock));  
  418.                 // curfds++;  
  419.                 // pthread_mutex_unlock (&(curfds_lock));  
  420.   
  421.   
  422.             }  
  423.             else  
  424.             {  
  425.                 printf("other event \n");  
  426.             }  
  427.         }  
  428.     }  
  429.     close(listener);  
  430.   
  431.     // pool_destroy ();  
  432.     return 0;  
  433. }  

tilera试用

 

tilera处理器架构

前段时间同事搞来了一台使用tilera处理器的服务器,没错,就是那个由MIT专家做的、64个核的处理器,我非常好奇,所以也登上去体验体验。

tilera在硬件之上做了一个薄薄的软件层,叫hypervisior,再在这个hypervisior上装了一个linux,然后是gcc/g++/gdb等一套工具链。当然,这个linux是改过的,在内核arch/tile/目录里增加了东西,但是即使是增加了kernel代码,也只能跑在hypervisior上,不能直接跑在tilera硬件上。

我们用的是tilepro处理器,32位,64个核,每个核却只有863MHZ,所以多进程/多线程的程序有福了,我试了一下make -j60,感觉上确实比较快,但是,configure就慢得夸张。

在tilera上安装apache+php的过程中遇到几个小问题,主要是因为这个linux环境比较荒芜:

1. 从源码安装软件时,运行./configure遇到“configure: error: C compiler cannot create executables”,解决方法:
export CC=”gcc”
export CPP=”gcc -E”

2. ./configure还会遇到不能识别当前机器的处理器类型,解决方法:
./configure --build=i386
不用担心这个欺骗性的i386选项,对于可移植的c代码软件,这样不会造成什么问题。

我安装php最后还是失败了,所以拉倒,改装nginx做测试,起了20个nginx进程,通过千兆网卡做压力,却只能达到3000左右的QPS,这显然太低了。于是问了tilera的技术支持,他反馈说他们做过memcached的实验(据他说,facebook已经在用tilera机器专跑memcached),能到60万QPS,但是nginx多进程却很慢,他们也很疑惑,目前还在研究为什么。

看来tilera的软件层目前还偏薄弱,等一段时间吧,等linux-2.6.36稳定,且tilera的3.0版本的开发工具套件变为stable,我们再来关注关注。



====== 2011.01.06 ======

今天tilera公司的顾冉同学发来新消息,他们就用和我们一样的硬件环境(一片tilepro)和软件环境(MDE-2.1.0),10个左右的并发nginx,达到了将近2万QPS,比x86上的apache差一些,但是比我的测试结果已经好很多了。
也许是我的配置有问题,有待以后研究了。



你可能感兴趣的:(Tilera多线程网络编程总结)