亚洲成精品动漫久久精久,九九在线精品视频播放,黄色成人免费观看,三级成人影院,久碰久,四虎成人欧美精品在永久在线

掃一掃
關(guān)注微信公眾號(hào)

介紹守護(hù)進(jìn)程XINETD與SOCKET程序的含義2
2007-06-26   中國(guó)IT實(shí)驗(yàn)室

6.xinetd 的工作原理

通過(guò)配置xinetd,然后查看相應(yīng)的套接字和進(jìn)程,可以看出,xinetd是這樣工作的(針對(duì)tcp服務(wù))

A.啟動(dòng)時(shí)讀取/etc/xinetd.conf文件并為文件中指定的所有服務(wù)創(chuàng)建相應(yīng)的套接字(流或數(shù)據(jù)報(bào)),xinetd能處理的服務(wù)的數(shù)目依賴(lài)于所創(chuàng)建的套接字?jǐn)?shù)目。每個(gè)新創(chuàng)建的套接字都被加入到select調(diào)用所用到的描述符集中。

B.對(duì)每一個(gè)套接字調(diào)用bind,綁定服務(wù)端口(/etc/services中定義),端口號(hào)通過(guò)調(diào)用getservbyname獲得。

C.所有套接字建立后,調(diào)用select等待它們變?yōu)榭勺x,當(dāng)tcp套接字上有數(shù)據(jù)報(bào)到來(lái)時(shí)變?yōu)榭勺x。xinetd在大部分時(shí)間阻塞在select的調(diào)用處;

D.xinetd守護(hù)進(jìn)程fork,由子進(jìn)程處理服務(wù)請(qǐng)求;子進(jìn)程關(guān)閉除了要處理的套接字之外的所有描述字,子進(jìn)程三次調(diào)用dup2,把套接字描述字復(fù)制到0、1、2,然后關(guān)閉原套接字;以后程序?qū)μ捉幼植僮骶褪菍?duì)0、1、2進(jìn)行操作;子進(jìn)程exec執(zhí)行相應(yīng)的服務(wù)器程序,并將配置文件中的參數(shù)傳遞。

E. 因?yàn)閠cp服務(wù)器通常設(shè)置nowait標(biāo)記,表示xinetd在該套接字上再次選擇之前,必須等待在該套接字上服務(wù)的子進(jìn)程終止。所以,父進(jìn)程中的fork返回時(shí),把子進(jìn)程的進(jìn)程號(hào)記錄下來(lái),這樣,在子進(jìn)程終止時(shí),父進(jìn)程可以用waitpid的返回值查知是那一個(gè)子進(jìn)程;父進(jìn)程用FD_CLR宏關(guān)閉select使用的描述字集中與這個(gè)套接字對(duì)應(yīng)的位,以便不對(duì)該套接字select;當(dāng)子進(jìn)程終止時(shí),父進(jìn)程收到一個(gè)SIGCHLD信號(hào),父進(jìn)程的信號(hào)處理程序得到終止子進(jìn)程的進(jìn)程號(hào),父進(jìn)程通過(guò)打開(kāi)描述字集中對(duì)應(yīng)的位恢復(fù)對(duì)該套接字的select。

7.重新實(shí)現(xiàn)的XINETD超級(jí)守護(hù)程序

A.程序利用上面的原理在思路上重新實(shí)現(xiàn)了超級(jí)守護(hù)進(jìn)程。

B.程序在一些地方只是概念性的代碼,完全實(shí)現(xiàn)還有待補(bǔ)充。

C.程序能演示XINETD 的功能,但是在注釋有BUG 和NOTE 的地方還需改進(jìn)

D.這是一個(gè)總結(jié)性的資料,參考了“利用INETD實(shí)現(xiàn)UDP守護(hù)進(jìn)程“和“www.douzhe.com“上的文章。

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

#include<netinet/in.h>
#include<sys/socket.h>

#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>

#include<errno.h>
#include <sys/ioctl.h>
//為每一個(gè)服務(wù)分配一個(gè)包含socket,及路徑的信息結(jié)構(gòu)。
struct param{
  int   sock;      //BIND的套接字     
  char  path[256]; //服務(wù)程序 路徑   
  pid_t  pid ;     //CHILD 進(jìn)程ID    
  struct param *next;  
}

fd_set readfds;
struct param *phead,*ptail,*p;

/*
 響應(yīng)子進(jìn)程結(jié)束的信號(hào)函數(shù);
 如果服務(wù)中wait=yes;
 則bind socket 必須等到子進(jìn)程結(jié)束才能監(jiān)聽(tīng)下一個(gè)請(qǐng)求
*/
void signal_handler(int signum)
{
  pid_t pid;
 
  pid= waitpid(-1,NULL,WUNTRACED);
 
  for(p=phead;p!=NULL;p=p->next)
      if(p->pid==pid)
 {
          //FD_SET(p->sock,&readfds);
          printf("child exit  pid= %d\n",pid);
          break;
        }
  signal(SIGCHLD,signal_handler);
}    


int main(int argc,char *argv[])
{
  int sock,ss;
  int nret;
  int sock_len;
  struct sockaddr_in addr;  
  struct sockaddr_in addr_clt;  
  FILE *file;
  fd_set testfds;

  sock_len=sizeof(addr);
  
 
  p=(struct param*)malloc(sizeof(struct param));
  ptail=p;
  phead=NULL;


  
  p->sock=socket(AF_INET,SOCK_STREAM,0);
     //  file=fopen("/etc/xinetd.conf","r");
     //  while(1)//省略從"/etc/xinetd.conf"文件中讀每一個(gè)服務(wù)并啟動(dòng)
  {
  addr.sin_family=AF_INET;
  addr.sin_addr.s_addr=htonl(INADDR_ANY); 
  addr.sin_port=htons(9734);//從“/etc/service”文件中讀服務(wù)的端口號(hào) getservbyname;
  bind(p->sock,(struct sockaddr *)&addr,sock_len);
  listen(p->sock,5); 

   FD_ZERO(&readfds);
   FD_SET(p->sock,&readfds);
   
    strcpy(p->path,"~/socket/");//省略從"/etc/xinetd.conf"文件中讀每一個(gè)服務(wù)的路徑
   if(phead==NULL)
    {
      p->next=NULL;
      phead=ptail=p;        
      printf("phead==null\n");
    }
  else
    { 
      ptail->next=p;
      ptail=p;
      ptail->next=NULL;

    }
   printf("path=%s,sock=%d\n",phead->path,phead->sock);
 }
  

  while(1)
{
  int fd;
  int clientfd;
  int n;
  pid_t pid;
  int flag=0;

  testfds=readfds;
  
   nret=select(FD_SETSIZE,&testfds,NULL,NULL,NULL);
   //if(nret<0){perror(strerror(errno));exit(5);}// bug 
1:如果子進(jìn)程END,會(huì)顯示“interrupt system call”錯(cuò)誤。 for(fd=0;fd<FD_SETSIZE;fd++) if(FD_ISSET(fd,&readfds)) { //bug 2:第一次接收到串“sock addr=3.190.0.64,client sock=4”
以后用LOOPBACK 連接返回為"127.0.0.1" clientfd=accept(fd,(struct sockaddr*)&addr_clt,&n); printf("sock addr=%s,client sock=%d\n",
     inet_ntoa(addr_clt.sin_addr),clientfd); pid=fork(); switch(pid) { case -1: perror("error"); exit(5); case 0: //dup2(clientfd,stdin); //dup2(clientfd,stdout); //dup2(clientfd,stderr); //close(clientfd); for(p=phead;p!=NULL;p=p->next) if(p->sock==fd) { printf("child runing \n"); //execve(); //note 1:未調(diào)用SERVER PATH(FILE) } sleep(1); exit(5); default:// >0 close(clientfd); if(flag) //note 2: 由service name 的wait 標(biāo)志決定 FD_CLR(fd,&readfds); for(p=phead;p!=NULL;p=p->next) if(p->sock==fd) { p->pid=pid; printf("sock:%d, child pid=%d\n",p->sock,p->pid); } signal(SIGCHLD,signal_handler);//note 3:放到開(kāi)始,還是這兒呢? break; } } } }

熱詞搜索:

上一篇:介紹守護(hù)進(jìn)程XINETD與SOCKET程序的含義1
下一篇:實(shí)用技巧:Linux系統(tǒng)下查CPU個(gè)數(shù)的方法

分享到: 收藏