好奇的探索者,理性的思考者,踏实的行动者。
Table of Contents:
函数查找匹配指定模式的文件名或目录。功能强大
#include <glob.h>
int glob(const char *pattern, int flags,int errfunc(const char *epath, int eerrno),glob_t *pglob);
属于stdlib.h中的,linux下,system()会调用fork()产生子进程,由子进程来用exec调用/bin/sh -c string来执行参数string字符串所代表的命令,此命令执行完后随即返回原调用的进程
system("start notepad"); 多个进程的打开(异步的打开)
system("notepad") 单个的打开(同步的打开)
system("pause"); cmd窗口的停止
system("explorer.exe C:\\Program Files"); 打开资源管理器并进入相应的目录
popen可以让你在 C++ 程序中执行 shell 命令,并且得到命令执行的结果
以下是对popen的封装,输入是执行的命令,输出是命令执行的结果
#include <iostream>
#include <stdexcept>
#include <stdio.h>
#include <string>
// cmd 是你要执行的命令
std::string exec(const char* cmd)
{128];
char buffer[// result 保存命令执行的结果
std::string result ;
"r");
FILE* pipe = popen(cmd,
if (!pipe) "popen() failed!");
throw std::runtime_error(
try
{//结果通过文件描述符进行读取
while (fgets(buffer, sizeof buffer, pipe) != NULL)
{
result += buffer ;
}
}
catch (...)
{
pclose(pipe);
throw ;
}
pclose(pipe);
return result ; }
C++11写法
#include <cstdio>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <array>
// cmd 是你要执行的命令
std::string exec(const char* cmd)
{char, 128> buffer ;
std::array<// result 保存命令执行的结果
std::string result ;
FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
std::unique_ptr<
if (!pipe)
{"popen() failed!");
throw std::runtime_error(
}
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr)
{
result += buffer.data();
}
return result ; }
system()、popen()给我们处理了fork、exec、waitpid等一系列的处理流程,让我们只需要关注最后的返回结果(函数的返回值)即可。
popen如何获取命令执行的结果?
命令执行时会将命令的结果输出到标准输出中,通过在父进程中创建一个管道,然后将标准输出到这个管道中,然后父进程从这个管道中读取结果。
从上面的源码可以看到system和popen都是执行了类似的运行流程,大致是fork->execl->return
。但是我们看到system在执行期间调用进程会一直等待shell命令执行完成(waitpid等待子进程结束)才返回,但是popen无须等待shell命令执行完成就返回了。我们可以理解system为串行执行,在执行期间调用进程放弃了”控制权”,popen为并行执行。
popen中的子进程没人给它”收尸”了啊?是的,如果你没有在调用popen后调用pclose那么这个子进程就可能变成”僵尸”。
上面我们没有给出pclose的源码,其实我们根据system的源码差不多可以猜测出pclose的源码就是system中第4部分的内容。
int system(const char *command)
{
struct sigaction sa_ignore, sa_intr, sa_quit;
sigset_t block_mask, orig_mask;
pid_t pid;
sigemptyset(&block_mask);
sigaddset(&block_mask, SIGCHLD);//1. block SIGCHLD
sigprocmask(SIG_BLOCK, &block_mask, &orig_mask);
sa_ignore.sa_handler = SIG_IGN;0;
sa_ignore.sa_flags =
sigemptyset(&sa_ignore.sa_mask);//2. ignore SIGINT signal
sigaction(SIGINT, &sa_ignore, &sa_intr); //3. ignore SIGQUIT signal
sigaction(SIGQUIT, &sa_ignore, &sa_quit);
switch((pid = fork()))
{1:
case -1;
return -0:
case
sigaction(SIGINT, &sa_intr, NULL);
sigaction(SIGQUIT, &sa_quit, NULL);
sigprocmask(SIG_SETMASK, &orig_mask, NULL);"/bin/sh", "sh", "-c", command, (char *) 0);
execl(127);
exit(
default:0) == -1) //4. wait child process exit
while(waitpid(pid, NULL,
{
if(errno != EINTR)
{
break;
}
}
}
}0; return
static pid_t *childpid = NULL; /* ptr to array allocated at run-time */
/* from our open_max(), {Prog openmax} */
static int maxfd;
#define SHELL "/bin/sh"
FILE *
popen(const char *cmdstring, const char *type)
{ 2];
int i, pfd[
pid_t pid;
FILE *fp;
/* only allow "r" or "w" */
0] != 'r' && type[0] != 'w') || type[1] != 0) {
if ((type[/* required by POSIX.2 */
errno = EINVAL;
return(NULL);
}
/* first time through */
if (childpid == NULL) { /* allocate zeroed out array for child pids */
maxfd = open_max();
if ( (childpid = calloc(maxfd, sizeof(pid_t))) == NULL)
return(NULL);
}
0)
if (pipe(pfd) < /* errno set by pipe() */
return(NULL);
0)
if ( (pid = fork()) < /* errno set by fork() */
return(NULL); 0) { /* child */
else if (pid == 'r') {
if (*type == 0]);
close(pfd[1] != STDOUT_FILENO) {
if (pfd[1], STDOUT_FILENO);
dup2(pfd[1]);
close(pfd[
}
} else { 1]);
close(pfd[0] != STDIN_FILENO) {
if (pfd[0], STDIN_FILENO);
dup2(pfd[0]);
close(pfd[
}
} /* close all descriptors in childpid[] */
0; i < maxfd; i++)
for (i = 0)
if (childpid[ i ] >
close(i);
"sh", "-c", cmdstring, (char *) 0);
execl(SHELL, 127);
_exit(
} /* parent */
'r') {
if (*type == 1]);
close(pfd[0], type)) == NULL)
if ( (fp = fdopen(pfd[
return(NULL);
} else { 0]);
close(pfd[1], type)) == NULL)
if ( (fp = fdopen(pfd[
return(NULL);
} /* remember child pid for this fd */
childpid[fileno(fp)] = pid;
return(fp); }