Clamav杀毒软件源码分析笔记 五

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

                 
  Clamav杀毒软件源码分析笔记[五]


刺猬@http://blog.csdn.net/littlehedgehog





[Socket通信]

扫描二维码关注公众号,回复: 4152307 查看本文章


套间字socket常用于服务/客户模型的应用程序之间的通信和数据连接,需要重点关注的是这个所谓的服务端/客户端完全可以是一台计算机的两个应用程序。前面我们已经提到了,Clamd就是这个服务端,也就是说它是整个程序的顶梁柱,所有的关键逻辑处理都是它一人为之,不可不谓之强悍。所有的这些功劳都应该归功于Clamd中的线程处理,不过我们先还不是来关注线程的,先看看socket的建立。


  1. int localserver(const struct optstruct *opt, const struct cfgstruct *copt, struct cl_node *root)
  2. {
  3.     struct sockaddr_un server;
  4.     int sockfd, backlog;
  5.     struct cfgstruct *cpt;
  6.     struct stat foo;
  7.     char *estr;

  8.     /* 下面是初始化套间字 顺便贴上了配置文件中有关localsocket的信息

  9.     # Path to a local socket file the daemon will listen on.
  10.     # Default: disabled
  11.     LocalSocket /tmp/clamd
  12.     */
  13.     memset((char *) &server, 0, sizeof(server));
  14.     server.sun_family = AF_UNIX;
  15.     strncpy(server.sun_path, cfgopt(copt, "LocalSocket")->strarg, sizeof(server.sun_path));

  16.     if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
  17.     {
  18.         estr = strerror(errno);
  19.         /*
  20.         fprintf(stderr, "ERROR: socket() error: %s/n", estr);
  21.         */
  22.         logg("!Socket allocation error: %s/n", estr);
  23.         exit(1);
  24.     }

  25.     if (bind(sockfd, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) == -1)
  26.     {
  27.         if (errno == EADDRINUSE)        //端口号或者socket被其他进程使用
  28.         {
  29.             if (connect(sockfd, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) >= 0)  //这里连接成功表明socket确实是被别的进程使用了
  30.             {
  31.                 close(sockfd);
  32.                 logg("!Socket file %s is in use by another process./n", server.sun_path);
  33.                 exit(1);
  34.             }
  35.             if (cfgopt(copt, "FixStaleSocket"))         //该socket不是被别的进程占据了,下面我们要做修复工作,配置文件中有FixStaleSocket 意思是要修理失效的socket
  36.             {
  37.                 logg("^Socket file %s exists. Unclean shutdown? Removing.../n", server.sun_path);
  38.                 if (unlink(server.sun_path) == -1)      //从文件系统中删除一个名称。如果名称是文件的最后一个连接,并且没有其它进程将文件打开,名称对应的文件会实际被删除。
  39.                 {
  40.                     estr = strerror(errno);
  41.                     logg("!Socket file %s could not be removed: %s/n", server.sun_path, estr);
  42.                     exit(1);
  43.                 }
  44.                 if (bind(sockfd, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) == -1)        //再次bind如果失败
  45.                 {
  46.                     estr = strerror(errno);
  47.                     logg("!Socket file %s could not be bound: %s (unlink tried)/n", server.sun_path, estr);
  48.                     exit(1);
  49.                 }
  50.             }
  51.             else if (stat(server.sun_path, &foo) != -1)
  52.             {
  53.                 logg("!Socket file %s exists. Either remove it, or configure a different one./n", server.sun_path);
  54.                 exit(1);
  55.             }
  56.         }
  57.         else        //这里出现了其他错误
  58.         {
  59.             estr = strerror(errno);
  60.             logg("!Socket file %s could not be bound: %s/n", server.sun_path, estr);
  61.             exit(1);
  62.         }
  63.     }

  64.     logg("Unix socket file %s/n", server.sun_path);

  65.     if ((cpt = cfgopt(copt, "MaxConnectionQueueLength")))   //Maximum length the queue of pending connections may grow to.  backlog参数为提出连接请求后,在服务器接收该连接请求时的等待队列中的连接数
  66.         backlog = cpt->numarg;
  67.     else
  68.         backlog = CL_DEFAULT_BACKLOG;

  69.     logg("Setting connection queue length to %d/n", backlog);

  70.     if (listen(sockfd, backlog) == -1)
  71.     {
  72.         estr = strerror(errno);
  73.         /*
  74.         fprintf(stderr, "ERROR: listen() error: %s/n", estr);
  75.         */
  76.         logg("!listen() error: %s/n", estr);
  77.         exit(1);
  78.     }

  79.     acceptloop_th(sockfd, root, copt);

  80.     return 0;
  81. }
注意这里建立的是本地socket的,区别比较大,但是在我这里唯一的区别就是加粗了,形成了很黑很粗壮的效果...


这里我们主要就是建立个socket的,其实也没啥好说的,主要是整个函数的调用,将改变整个历史进程方向──acceptloop_th(sockfd, root, copt);  因为我们要被一直束缚在里面,貌似永世不得超生了。


acceptloop_th 很长很强大,所以我也就不把源码贴出来了,否则有凑字数的嫌疑,重点关注下下面一块:


  1.  /* set up signal handling */
  2.     sigfillset(&sigset);
  3.     sigdelset(&sigset, SIGINT);
  4.     sigdelset(&sigset, SIGTERM);
  5.     sigdelset(&sigset, SIGSEGV);
  6.     sigdelset(&sigset, SIGHUP);
  7.     sigdelset(&sigset, SIGPIPE);
  8.     sigdelset(&sigset, SIGUSR2);
  9.     sigprocmask(SIG_SETMASK, &sigset, NULL);        //通过这条语句 进程有了新的信号屏蔽集 这里是屏蔽一些我们不关心的信号 

  10.     /* SIGINT, SIGTERM, SIGSEGV */
  11.     sigact.sa_handler = sighandler_th;
  12.     sigemptyset(&sigact.sa_mask);
  13.     sigaddset(&sigact.sa_mask, SIGINT);
  14.     sigaddset(&sigact.sa_mask, SIGTERM);
  15.     sigaddset(&sigact.sa_mask, SIGHUP);
  16.     sigaddset(&sigact.sa_mask, SIGPIPE);
  17.     sigaddset(&sigact.sa_mask, SIGUSR2);
  18.     sigaction(SIGINT, &sigact, NULL);               //下面都是安装新的信号处理程序 
  19.     sigaction(SIGTERM, &sigact, NULL);
  20.     sigaction(SIGHUP, &sigact, NULL);
  21.     sigaction(SIGPIPE, &sigact, NULL);
  22.     sigaction(SIGUSR2, &sigact, NULL);

为什么这里需要重新设定这么多的信号处理呢?原因就是我们要屏蔽或者拦截其中有些信号,做出相应的反应,这貌似是废话...???? 比如SIGINT,这信号会导致进程终止,我们需要在终止之前把记录写入log文件,ok,必须拦截信号函数.





           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_43678612/article/details/84071415