網路斷線檢測中用到的popen

sgy618發表於2011-01-17

網路斷線檢測中用到的popen

[@more@]

/**
* @fn netPing
* @brief 獲取Ping狀態
* @param[in]
* @param[out]
* @return 0: down, 1: up
*/
int netPing(void)
{
int i = 0;
int ret = APP_FAIL;
uint networkByteOrder;
char buf[MAX_CMD_LEN] = {0};
char strbuf[100] = {0};
FILE *fd = NULL;

networkByteOrder = htonl(pSetupSetPing->detectIpAddr);
sprintf(strbuf, "/usr/local/sbin/ping -c 4 -t 1 %s", inet_ntoa(*(struct in_addr*)(&networkByteOrder)));

for(i = 0; i < pSetupSetPing->retryTimes; i++)
{
fd = popen(strbuf, "r");
if (NULL == fd)
{
perror("popen");
dbgPrintfl(DETAIL, "popen ping fail!n");
ret = APP_FAIL;
goto out;
}

dataNoBlockFgets(buf, sizeof(buf), fd);

if(0 == strlen(buf)) //ping失敗
{
dbgPrintfl(DETAIL, "ping fail!n");
ret = APP_FAIL;
continue;
}
else
{
ret = APP_OK;
break;
}
}

out:
if(fd != NULL)
{
pclose(fd);
fd = NULL;
}

return ret;
}


/**
* @fn dataNoBlockFgets
* @brief 本地實現替換fgets的非阻塞版本
* @param[in] int size:待讀取長度
* FILE* stream:讀取的流
* @param[out] char* s:讀取輸出
* @return
*/
static char* dataNoBlockFgets(char *s, int size, FILE* stream)
{
int ret = 0;
int fno = -1;
fd_set rfds;
int maxFd;
struct timeval timeout;

fno = fileno(stream);
memset(s, 0, size);
do{
maxFd = 0;
FD_ZERO(&rfds);
FD_SET(fno, &rfds);

maxFd = maxFd > fno ? maxFd : fno;
maxFd += 1;

timeout.tv_sec = 2;
timeout.tv_usec = 0;

ret = select(maxFd, &rfds, NULL, NULL, &timeout);
if(ret > 0)
{
if(FD_ISSET(fno, &rfds))
{
read(fno, s, size);
}
}
}while(0);

dbgPrint(DETAIL, "%sn", s);

return s;
}

popen:
  程式I/O函式,與pclose函式一起使用。
表標頭檔案
  #include
函式定義
  FILE * popen ( const char * command , const char * type );
  int pclose ( FILE * stream );
函式說明
  popen() 函式透過建立一個管道,呼叫 fork 產生一個子程式,執行一個 shell 以執行命令來開啟一個程式。這個程式必須由 pclose() 函式關閉,而不是 fclose() 函式。pclose() 函式關閉標準 I/O 流,等待命令執行結束,然後返回 shell 的終止狀態。如果 shell 不能被執行,則 pclose() 返回的終止狀態與 shell 已執行 exit 一樣。
   type 引數只能是讀或者寫中的一種,得到的返回值(標準 I/O 流)也具有和 type 相應的只讀或只寫型別。如果 type 是 "r" 則檔案指標連線到 command 的標準輸出;如果 type 是 "w" 則檔案指標連線到 command 的標準輸入。
   command 引數是一個指向以 NULL 結束的 shell 命令字串的指標。這行命令將被傳到 bin/sh 並使用-c 標誌,shell 將執行這個命令。
   popen 的返回值是個標準 I/O 流,必須由 pclose 來終止。前面提到這個流是單向的。所以向這個流寫內容相當於寫入該命令的標準輸入;命令的標準輸出和呼叫 popen 的程式相同。與之相反的,從流中讀資料相當於讀取命令的標準輸出;命令的標準輸入和呼叫 popen 的程式相同。
返回值
  如果呼叫 fork() 或 pipe() 失敗,或者不能分配記憶體將返回NULL,否則返回標準 I/O 流。
返回錯誤
  popen 沒有為記憶體分配失敗設定 errno 值。
  如果呼叫 fork() 或 pipe() 時出現錯誤,errno 被設為相應的錯誤型別。
  如果 type 引數不合法,errno將返回EINVAL。
使用舉例
  if((fp=popen("/usr/bin/uptime","r"))==NULL);
  {
  sprintf(buf,"error: %sn", strerror(errno));
  ....//異常處理
  }
  else
  {
  ....
  pclose(fp);
  }

函式原型:int _fileno( FILE *stream );
函式功能:fileno()用來取得引數stream指定的檔案流所使用的檔案描述符
返回值:某個資料流的檔案控制程式碼
標頭檔案:stdio.h

例子:
int main(void)
  {
  FILE *fp;
  int fd;
  fp = fopen("/etc/passwd", "r");
  fd = fileno(fp);
  printf("fd = %dn", fd);
  fclose(fp);
  return 0;
  }

#define fileno(__p) ((__p)->_file)
  因為FILE 結構體定義為
  類似
  typedef struct {
  unsigned char *_ptr;
  int _cnt;
  unsigned char *_base;
  unsigned char *_bufendp;
  short _flag;
  short _file;
  int __stdioid;
  char *__newbase;
  void *_lock;
  } FILE;
  其中 _file就是檔案描述符。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23168012/viewspace-1044778/,如需轉載,請註明出處,否則將追究法律責任。

相關文章