linux c redirect 重定向
用execvp实现时,运行adb,如果adb 服务没有启动,会启动adb服务,启动adb服务时,pipe返回的管道在读的时候堵塞了。
查看了popen的源码,发现popen是用sh -c来执行的,避免了这个问题
不知道sh -c做了些什么操作,使得popen可以避免这个问题
代码如下:
#ifndef __RG_REDIRECT_H
#define __RG_REDIRECT_H //#ifdef _LINUX //for linux version #include <string> #ifdef _LINUX
#include <signal.h>
#endif #define WAIT_FOREVER 0 typedef void (*pReDirectCallBack)(const char* strOutput, bool bOver); class CRGReDirect
{
public:
CRGReDirect();
~CRGReDirect(); public:
//同步方式运行ADB命令,会阻塞。命令结果保存在strResult里面返回
//strCmd是需要执行的ADB命令。例如:adb_path devices
int RunCmdSync(std::string& strResult, const std::string& strCmd);
int RunCmdSync(std::string& strResult, const char *szCmd); //nTimeOut单位是秒
int RunCmdWithTimeOut(std::string& strResult, const std::string& strCmd, int nTimeOut = WAIT_FOREVER);
int RunCmdWithTimeOut(std::string& strResult, const char *szCmd, int nTimeOut = WAIT_FOREVER); //异步方式执行ADB命令,不会阻塞,直接返回线程的pid(失败返回-1)
//strCmd是需要执行的ADB命令。例如:adb_path devices
//ADB运行完成之后主动条用CallBack函数pFunc
//成功返回非零,失败返回-1
int RunCmdAsync(pReDirectCallBack pFunc, const std::string&strCmd);
int RunCmdAsync(pReDirectCallBack pFunc, const char *szCmd);
// const char* GetCmdResultString(void) const { return m_strResult.c_str(); } protected:
int RunCmd(pReDirectCallBack pFunc = NULL); void CancelCommand(); #ifdef _WIN32
HANDLE m_hTimer;
HANDLE m_hTimerQueue;
HANDLE m_hChildProcess; HANDLE m_hCmdThread;
static DWORD WINAPI RunProcess(void *arg);
static VOID CALLBACK HandleTimeOut( PVOID lpParameter, BOOLEAN TimerOrWaitFired);
#else
int SetTimer(int nSeconds, int nTimerID);
int KillTimer(timer_t nTimerID); timer_t m_timer_id;
pthread_t m_thread_id;
static void* RunProcess(void* arg);
static void HandleTimeOut(sigval_t v); pid_t *m_childpid; /* ptr to array allocated at run-time */
int m_maxfd; /* from our open_max(), {Prog openmax} */
FILE* m_hChildProcess; int open_max(void);
FILE * rgpopen(const char *cmdstring, const char *type); //模拟popen实现的版本
int rgpkill(FILE* fp); //根据文件指针关掉相应的进程
int rgpclose(FILE *fp); //关闭文件指针
#endif private:
std::string m_strResult;
std::string m_strCmd;
pReDirectCallBack m_adbCB;
volatile bool m_bAbort;
}; //#endif #endif
#ifndef _WIN32
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <pthread.h> // Compile and link with -pthread.
#include <cstring>
#include <cstdlib>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <errno.h>
#else
#include <Windows.h>
#endif #include "RGReDirect.h"
#include <cassert>
#include <cstdio> #define RG_TIMER_ID 51
std::string Trim(const std::string& strIn)
{
std::string strMatch = " \t\r\n";
size_t i = strIn.find_first_not_of(strMatch);
size_t j = strIn.find_last_not_of(strMatch);
if (i != std::string::npos)
return strIn.substr(i, j-i+1);
return "";
}
CRGReDirect::CRGReDirect()
: m_adbCB(NULL)
#ifdef _WIN32
, m_hChildProcess(NULL)
, m_hCmdThread(NULL)
, m_hTimer(NULL)
, m_hTimerQueue(NULL)
#else
, m_thread_id()
, m_timer_id()
, m_childpid(NULL)
, m_maxfd()
, m_hChildProcess(NULL)
#endif
, m_bAbort(false)
{
} CRGReDirect::~CRGReDirect()
{
#ifdef _WIN32
if (m_hCmdThread)
{
WaitForSingleObject(m_hCmdThread, INFINITE);
CloseHandle(m_hCmdThread);
}
if (m_hTimer) DeleteTimerQueueTimer(m_hTimerQueue, m_hTimer, NULL);
if (m_hTimerQueue) DeleteTimerQueue(m_hTimerQueue); #else
if (m_thread_id) pthread_join(m_thread_id, NULL);
if(m_timer_id) timer_delete(m_timer_id);
if(m_childpid) free(m_childpid);
#endif
} int CRGReDirect::RunCmd(pReDirectCallBack pFunc /* = NULL */)
{
m_bAbort = false;
m_strResult.clear(); #ifdef _WIN32
std::string strTmpCmd = m_strCmd;
HANDLE hChildStdoutRd, hChildStdoutWr, hStdout;
SECURITY_ATTRIBUTES saAttr; // Set the bInheritHandle flag so pipe handles are inherited.
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL; // Get the handle to the current STDOUT.
hStdout = GetStdHandle(STD_OUTPUT_HANDLE); // Create a pipe for the child process's STDOUT.
if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, ))
return -; // Ensure the read handle to the pipe for STDOUT is not inherited.
SetHandleInformation( hChildStdoutRd, HANDLE_FLAG_INHERIT, ); char *szCmdline = new char[strTmpCmd.size() + ];
memset(szCmdline, , strTmpCmd.size() + );
strcpy(szCmdline, strTmpCmd.c_str()); PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo; // Set up members of the PROCESS_INFORMATION structure.
ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) ); // Set up members of the STARTUPINFO structure.
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = hChildStdoutWr;
siStartInfo.hStdOutput = hChildStdoutWr;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES; // Create the child process.
BOOL bFuncRetn = CreateProcess(NULL,
szCmdline, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
CREATE_NO_WINDOW, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION if (bFuncRetn == )
{
delete [] szCmdline;
return -;
}
else
{
m_hChildProcess = piProcInfo.hProcess;
CloseHandle(piProcInfo.hThread); const int BUFSIZE = ;
DWORD dwRead;
char chBuf[BUFSIZE] = {}; // Close the write end of the pipe before reading from the
// read end of the pipe.
if (!CloseHandle(hChildStdoutWr))
{
delete [] szCmdline;
return -;
} // Read output from the child process
while (m_bAbort == false)
{
if( !ReadFile( hChildStdoutRd, chBuf, BUFSIZE, &dwRead,
NULL) || dwRead == ) break;
chBuf[dwRead] = '\0';
if(pFunc) pFunc(chBuf, false);
else m_strResult += chBuf;
} CloseHandle(hChildStdoutRd); if(m_bAbort == false) //非终止进程,则自然关闭
{
CloseHandle(m_hChildProcess);
m_hChildProcess = NULL;
} if(pFunc) pFunc("", true); delete [] szCmdline;
return ;
} #else char line[] = {};
std::string strTmpCmd = m_strCmd + " 2>&1"; //重定向stderr至stdout if((m_hChildProcess = rgpopen(strTmpCmd.c_str(), "r")) == NULL)
{
fprintf(stderr, "rgpopen error\n");
return -;
} while(m_bAbort == false)
{
if(fgets(line, , m_hChildProcess) == NULL)
break;
if(pFunc) pFunc(line, false);
else m_strResult += line;
} if(pFunc) pFunc("", true); if (m_bAbort == false) //非终止进程,则自然关闭
{
rgpclose(m_hChildProcess);
m_hChildProcess = NULL;
} return ; #endif
} int CRGReDirect::RunCmdSync(std::string& strResult, const std::string& strCmd)
{
return RunCmdSync(strResult, strCmd.c_str());
} int CRGReDirect::RunCmdSync(std::string& strResult, const char *szCmd)
{
m_strCmd = szCmd;
m_adbCB = NULL; int nRet = RunCmd(m_adbCB); strResult = m_strResult; return nRet;
} int CRGReDirect::RunCmdAsync(pReDirectCallBack pFunc, const std::string&strCmd)
{
return RunCmdAsync(pFunc, strCmd.c_str());
} int CRGReDirect::RunCmdAsync(pReDirectCallBack pFunc, const char *szCmd)
{
assert(pFunc); m_adbCB = pFunc;
m_strCmd = szCmd; #ifdef _WIN32
DWORD dwThread;
HANDLE hThread = CreateThread(NULL, , RunProcess, this, , &dwThread);
if (hThread)
{
m_hCmdThread = hThread;
return ;
}
else
{
return -;
}
#else
pthread_t pid; if (pthread_create(&pid, NULL, RunProcess, this) == )
{
m_thread_id = pid;
return ;
}
else
{
return -;
}
#endif
} int CRGReDirect::RunCmdWithTimeOut(std::string& strResult, const std::string& strCmd, int nTimeOut)
{
return RunCmdWithTimeOut(strResult, strCmd.c_str(), nTimeOut);
} int CRGReDirect::RunCmdWithTimeOut(std::string& strResult, const char* szCmd, int nTimeOut)
{
if(nTimeOut == WAIT_FOREVER)
{
return RunCmdSync(strResult, szCmd);
} m_adbCB = NULL;
m_strCmd = szCmd; #ifdef _WIN32
DWORD dwThread;
HANDLE hThread = CreateThread(NULL, , RunProcess, this, , &dwThread);
if (hThread)
{
m_hCmdThread = hThread;
m_hTimerQueue = CreateTimerQueue();
CreateTimerQueueTimer(&m_hTimer, m_hTimerQueue, HandleTimeOut, this, nTimeOut * , , ); WaitForSingleObject(m_hCmdThread, INFINITE);
CloseHandle(m_hCmdThread);
m_hCmdThread = NULL; DeleteTimerQueueTimer(m_hTimerQueue, m_hTimer, NULL);
DeleteTimerQueue(m_hTimerQueue);
m_hTimer = m_hTimerQueue = NULL; strResult = m_strResult; LOG("%s\n", strResult); return ;
}
else
{
return -;
}
#else
pthread_t pid; if (pthread_create(&pid, NULL, RunProcess, this) == )
{
m_thread_id = pid; SetTimer(nTimeOut, RG_TIMER_ID); pthread_join(m_thread_id, NULL);
m_thread_id = ; KillTimer(m_timer_id);
m_timer_id = ;
strResult = m_strResult; return ;
}
else
{
return -;
}
#endif
} #ifdef _WIN32
void CRGReDirect::HandleTimeOut(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
#else
void CRGReDirect::HandleTimeOut(sigval_t v)
#endif
{
#ifdef _WIN32
CRGReDirect* pThis = (CRGReDirect*)lpParameter;
#else
CRGReDirect* pThis = (CRGReDirect*)(v.sival_ptr);
#endif
if (pThis)
{
printf("cancel command on timeout\n");
pThis->CancelCommand();
} #ifdef _DEBUG
printf("TimeOut on exit.\n");
#endif
} void CRGReDirect::CancelCommand()
{
m_bAbort = true; #ifdef _WIN32
if (m_hChildProcess) //进程未退出,强行终止
{
TerminateProcess(m_hChildProcess, );
CloseHandle(m_hChildProcess);
m_hChildProcess = NULL;
}
#else
if (m_hChildProcess)
{
rgpkill(m_hChildProcess);
m_hChildProcess = NULL;
}
#endif
} #ifdef _WIN32
DWORD WINAPI CRGReDirect::RunProcess(void* arg)
#else
void* CRGReDirect::RunProcess(void* arg)
#endif
{
CRGReDirect* pThis = (CRGReDirect *)arg;
assert(pThis); pThis->RunCmd(pThis->m_adbCB); #ifdef _WIN32
return ;
#else
return (void *);
#endif
} #ifndef _WIN32
int CRGReDirect::SetTimer(int nSeconds, int nTimerID)
{
timer_t tid;
struct sigevent se; memset(&se, , sizeof(se));
se.sigev_notify = SIGEV_THREAD;
se.sigev_notify_function = HandleTimeOut;
se.sigev_value.sival_ptr = this; if(timer_create(CLOCK_REALTIME, &se, &tid) < )
{
#ifdef _DEBUG
perror("timer_create:");
#endif
return -;
} struct itimerspec ts, ots;
ts.it_value.tv_sec = nSeconds;
ts.it_value.tv_nsec = ;
ts.it_interval.tv_sec = ;
ts.it_interval.tv_nsec = ; if(timer_settime(tid, , &ts, &ots) < )
{
#ifdef _DEBUG
perror("timer_settime:");
#endif
return -;
} m_timer_id = tid; return ;
} int CRGReDirect::KillTimer(timer_t nTimerID)
{
return timer_delete(nTimerID);
} #ifdef _ARM
#define SHELL "/system/bin/sh"
#else
#define SHELL "/bin/sh"
#endif int CRGReDirect::open_max()
{
struct rlimit rl;
if(getrlimit(RLIMIT_NOFILE, &rl) == )
return rl.rlim_max; return ; //default
} FILE* CRGReDirect::rgpopen(const char *cmdstring, const char *type)
{
int i, pfd[];
pid_t pid;
FILE *fp; /* only allow "r" or "w" */
if ((type[] != 'r' && type[] != 'w') || type[] != ) {
errno = EINVAL;
return(NULL);
} if (m_childpid == NULL) { /* first time through */
/* allocate zeroed out array for child pids */
m_maxfd = open_max();
if ( (m_childpid = (pid_t *)calloc(m_maxfd, sizeof(pid_t))) == NULL)
return(NULL);
} if (pipe(pfd) < )
return(NULL); /* errno set by pipe() */ if ( (pid = fork()) < )
return(NULL); /* errno set by fork() */
else if (pid == ) { /* child */
if (*type == 'r') {
close(pfd[]);
if (pfd[] != STDOUT_FILENO) {
dup2(pfd[], STDOUT_FILENO);
close(pfd[]);
}
} else {
close(pfd[]);
if (pfd[] != STDIN_FILENO) {
dup2(pfd[], STDIN_FILENO);
close(pfd[]);
}
}
/* close all descriptors in childpid[] */
for (i = ; i < m_maxfd; i++)
if (m_childpid[ i ] > )
close(i); execl(SHELL, "sh", "-c", cmdstring, (char *) );
_exit();
}
/* parent */
if (*type == 'r') {
close(pfd[]);
if ( (fp = fdopen(pfd[], type)) == NULL)
return(NULL);
} else {
close(pfd[]);
if ( (fp = fdopen(pfd[], type)) == NULL)
return(NULL);
}
m_childpid[fileno(fp)] = pid; /* remember child pid for this fd */
return(fp);
} int CRGReDirect::rgpkill(FILE* fp)
{
int fd, stat;
pid_t pid; if (m_childpid == NULL)
return(-); /* rgpopen() has never been called */ fd = fileno(fp);
if ( (pid = m_childpid[fd]) == )
return(-); /* fp wasn't opened by rgpopen() */ m_childpid[fd] = ;
fclose(fp); return kill(pid, SIGKILL);
} int CRGReDirect::rgpclose(FILE *fp)
{
int fd, stat;
pid_t pid; if (m_childpid == NULL)
return(-); /* rgpopen() has never been called */ fd = fileno(fp);
if ( (pid = m_childpid[fd]) == )
return(-); /* fp wasn't opened by rgpopen() */ m_childpid[fd] = ;
if (fclose(fp) == EOF)
return(-); while (waitpid(pid, &stat, ) < )
if (errno != EINTR)
return(-); /* error other than EINTR from waitpid() */ return(stat); /* return child's termination status */
} #endif
linux c redirect 重定向的更多相关文章
- Linux管道及重定向
Linux管道及重定向 对shell有一定了解的人都知道,管道和重定向是 Linux 中非常实用的 IPC 机制.在shell中,我们通常使用符合'|'来表示管道,符号'>'和'<'表示重 ...
- Linux I/O 重定向详解及应用实例
Linux I/O 重定向详解及应用实例 简解 > 输出 < 输入 >> 追加 & [> | < | >>]之前:输入输出; ls /dev & ...
- Linux下Shell重定向
1. 标准输入,标准输出与标准错误输出 Linux下系统打开3个文件,标准输入,标准输出,标准错误输出. 标准输入:从键盘输入数据,即从键盘读入数据. 标准输出:把数据输出到终端上. 标准错误输出:把 ...
- Linux I/O重定向
所谓I/O重定向简单来说就是一个过程,这个过程捕捉一个文件,或者命令,程序,脚本,甚至脚本中的代码块的输出,然后把捕捉到的输出,作为输入 发送给另外一个文件,命令,程序,或者脚本.谈到I/O重定向,就 ...
- Linux入门-7 Linux管道、重定向以及文本处理
Linux管道.重定向以及文本处理 1 Linux多命令协作:管道及重定向 管道和重定向 2 Linux命令行文本处理工具 文件浏览 基于关键字搜索-grep 基于列处理文本-cut 文本统计-wc ...
- (转)linux exec与重定向
原文:http://xstarcd.github.io/wiki/shell/exec_redirect.html linux exec与重定向 exec和source都属于bash内部命令(buil ...
- Linux标准输入、重定向与参数传递
Linux标准输入.重定向与参数传递 按惯例,每当运行一个新程序时,所有shell都为其打开3个文件描述符,即标准输入.标准输出以及标准错误.如果不做特殊处理,例如就像简单的命令ls,则这三个描述符都 ...
- linux中nginx重定向方法总结
linux中nginx 301重定向跳转方法总结 第一种情况:访问aaaaaaa站定向到bbbbbbbbbbb站 复制代码代码如下: server { server_naaaaaaame www.aa ...
- 【Linux】数据流重定向
数据流重定向(redirect)就是将某个命令执行后应该要出现在屏幕上的数据,给它传输到其他的地方,例如文件或设备(打印机之类的).这玩意在Linux的命令行模式下很重要,尤其是想要将某些数据存储下来 ...
随机推荐
- Hibernate一 入门
一 简介1.什么是ORMObject/Relation Mapping,即对象/关系映射.可以将其理解为一种规范,具体的ORM框架可以作为应用程序和数据库的桥梁.面向对象程序设计语言与关系数据库发展不 ...
- JavaBean基础
JavaBean的概念 JavaBean是一种可重复使用.且跨平台的软件组件.JavaBean可分为两种:一种是有用户界面(UI,User Interface)的JavaBean:还有一种是没有用户界 ...
- js~fancybox为我们提供的iframe功能
对于fancybox我们已经耳熟能详了,一般用来到表单的弹框,提示弹框等,而今天,我们将分页列表也使用fancybox来实现一下,这东西听起来简单,但做起来还真不是那么回事,有事细节需要我们注意的,首 ...
- 【JS跨域请求】Ajax跨域请求JSONP
前两天被问到ajax跨域如何解决,还真被问住了,光知道有个什么jsonp,迷迷糊糊的没有说上来.抱着有问题必须解决的态度,我看了许多资料,原来如此... 为何一直知道jsonp,但一直迷迷糊糊的不明白 ...
- android EditText中的inputType
android 1.5以后添加了软件虚拟键盘的功能,所以在输入提示中将会有对应的软键盘模式 android中inputType属性在EditText输入值时启动的虚拟键盘的风格有着重要的作用.这也大大 ...
- Android中使用HttpGet和HttpPost访问HTTP资源
需求:用户登录(name:用户名,pwd:密码) (一)HttpGet :doGet()方法//doGet():将参数的键值对附加在url后面来传递 public String getResultFo ...
- POJ 2559 Largest Rectangle in a Histogram (单调栈或者dp)
Largest Rectangle in a Histogram Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 15831 ...
- HUD3336
/* 巧妙地使用fail数组 根据fail数组的定义 fail[i] 有 长度为i的子串最长公共前后缀为fail[i] 比如样例 fail 0 0 1 2 那么我们维护一个ans[i]表示到i位置的时 ...
- matlab中的三维坐标系与旋转
1. matlab中的三维坐标系 matlab中的三维坐标系是使用的右手坐标系: 输入以下代码: >> plot3(0,0,0) >> xlabel('axis X') > ...
- jvm-初探
目录 1,Java体系结构 2.jvm执行引擎 3,ClassLoader的体系结构 4,java class文件 概述 其实,学java不算新手了,但是却感觉很多基本的知识,我们一开始也许是记住而不 ...