system函数

// system_exe.cc
#include <cassert>
#include <spdlog/common.h>
#include <spdlog/spdlog.h>
#include <string>
#include <unistd.h>

int main(int argc, char *argv[]) {
  assert(argc >= 2);
  spdlog::set_level(spdlog::level::debug);
  std::string buff;
  for (int i = 1; i < argc; ++i) {
    spdlog::debug("append arg [{0}]", argv[i]);
    buff.append(argv[i]);
    buff.append(" ");
  }
  spdlog::info("system({0})", buff);
  auto ret = system(buff.c_str());
  spdlog::info("return {0}", ret);
  return ret;
}
g++ -o system_exe -lspdlog system_exe.cc

exec系列函数

execv

函数声明
extern int execv(const char* __path,char *const* __argv[]);
__path: 是要执行程序的绝对路径。
__argv: 传入的参数数组,以nullptr结尾。

直接使用

// exe_agent_fst.cc
#include <cassert>
#include <cstring>
#include <mcheck.h>
#include <spdlog/common.h>
#include <spdlog/spdlog.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  setenv("MALLOC_TRACE", "output.log", 1); // 重定向malloc_trace的标准输出到output.log
  mtrace();
  spdlog::set_level(spdlog::level::debug);
  assert(argc >= 2);
  char **args_ = (char **)malloc(sizeof(char *) * argc);
  for (int i = 2, j = 0; i < argc; ++i, ++j) {
    args_[j] = argv[i];
  }
  args_[argc - 1] = nullptr;
  spdlog::info("execv {0} ...", argv[1]);
  auto result = execv(argv[1], args_);
  // 程序不能执行的话返回-1,如果程序成功执行进程将交给argv[1],后面的程序不会执行
  spdlog::info("execv result: {0}", result);
  free(args_);
  spdlog::debug("delete[] args_");
  return result;
}
g++ -g -o exe_agent_fst -lspdlog exe_agent_fst.cc
./exe_agent_fst /usr/bin/ls . # 程序能成功执行
mtrace ./exe_agent_fst output.log # 显示exe_agent_fst.cc:14 发生了内存泄漏

利用fork

// exe_agent_snd.cc
#include <cassert>
#include <cstring>
#include <spdlog/common.h>
#include <spdlog/spdlog.h>
#include <unistd.h>
#include <wait.h>
const int kMaxArgc = 2048;

int main(int argc, char *argv[]) {
  assert(2 <= argc && argc <= kMaxArgc);
  spdlog::set_level(spdlog::level::debug);
  auto pid = fork();
  if (pid < 0) {
    spdlog::error("error happend:{0}", strerror(errno));
    exit(-1);
  } else if (pid > 0) {
    int status_;
    auto _pid = waitpid(pid, &status_, 0);
    spdlog::info("pid[{0}] return[{1}] status[{2}]", pid, _pid, status_);
  } else {
    char *args_[kMaxArgc];
    for (int i = 0, j = 2; j < argc; ++j, ++i) {
      args_[i] = argv[j];
    }
    args_[argc - 2] = nullptr;
    auto ret = execv(argv[1], args_);
    spdlog::error("{0}! process {1} error!", ret, argv[1]);
  }

  return 0;
}
# makefile
cc=g++
exe_agent:exe_agent_snd.cc
	$(cc) -o $@ -lspdlog $<  
make 
./exe_agent /usr/bin/false 
./exe_agent /usr/bin/true
./exe_agent /usr/bin/ls .

利用pipe进行进程间通信

#include <cstdio>
#include <spdlog/common.h>
#include <spdlog/spdlog.h>
#include <string>
#include <sys/wait.h>
#include <unistd.h>

static const int kMaxArgc = 1024;
int main(int argc, char *argv[]) {
  assert(2 <= argc && argc < kMaxArgc);
  spdlog::set_level(spdlog::level::debug);
  int mypipe[2];
  pipe(mypipe); // 构建一个pipe,mypipe[1]用于write,mypipe[0]用于读
  auto pid = fork();
  if (pid < 0) {
    spdlog::error("fork error:{0}", strerror(errno));
    return -1;
  } else if (pid > 0) {
    close(mypipe[1]);
    auto fd = fdopen(mypipe[0], "r");
    std::string msg_;
    while (!feof(fd)) {
      msg_.push_back(std::fgetc(fd));
    }
    msg_.pop_back();
    spdlog::info("pid[{0}] output:{1}", pid, msg_);
    int status_;
    waitpid(pid, &status_, 0);
    spdlog::info("pid[{0}] return[{1}]", pid, status_);
  } else {
    char *args_[kMaxArgc];
    for (int i = 0, j = 2; j < argc; ++i, ++j) {
      args_[i] = argv[j];
    }
    args_[argc - 2] = nullptr;
    dup2(mypipe[1], STDOUT_FILENO);
    close(mypipe[0]);
    auto ret = execv(argv[1], args_);
    spdlog::error("execv({0},...) error {1}:{2}", argv[1], ret,
                  strerror(errno));
    return ret;
  }

  return 0;
}

  • mtrace 安装
sudo yum install glibc-utils.x86_64 # readhat ...
or
sudo apt-get install glibc-utils # debian ...
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐