【问题标题】:Is here has "CreatePipe" and "CreateProcessW" function in Linux?Linux中是否有“CreatePipe”和“CreateProcessW”功能?
【发布时间】:2020-02-18 14:16:20
【问题描述】:

如何在Linux中使用“CreatePipe”和“CreateProcessW”函数,当我在Linux中编译C++代码时,出现如下错误: 'CreatePipe' is not declared in this scope。 'CreateProcessW' 未在此范围内声明。

【问题讨论】:

  • CreateProcessW 似乎来自 Windows API?如果是这样,那不是语言标准的一部分,您需要找到(如果有的话)Linux 或 POSIX 等价物(换句话说,您不能期望使用任何 Windows API 的 C++ 代码在没有一些重大变化)。
  • 这些是 Windows 系统调用。我认为最接近 POSIX/linux/etc。相当于CreatePipe() 将是mkfifo() 如果你想要一个命名管道和pipe() 对于一个匿名管道(我不记得Windows函数是哪个)
  • popen 可能是一个选项。
  • 直接使用API​​没有什么不好,因为它可以优化代码。但它应该在您的应用程序的最低级别完成。如果你想把它移植到不同的系统上,你可以用新系统上更好的东西重写那个低层。但是试图在另一个系统上模仿一个系统的低级实现是错误的...... 勇敢
  • CreateProcessW 可能最接近于posix_spawn()CreatePipe 创建一个匿名管道 - POSIX 中的类似物是 pipe()

标签: c++ linux process pipe


【解决方案1】:

Posix/Linux:

int pipe(int pipefd[2]);

pipefd[0] 指管道的读端。
pipefd[1] 指管道的写端。

Linux 特定:

int pipe2(int pipefd[2], int flags);

说到CreateProcess,Posix/Linux 版本只需几步即可完成。

  • 调用fork() 来创建一个新进程——仍然运行同一个程序——所以两个进程现在将从调用fork() 的同一点继续运行同一个程序。通过检查 fork() 的返回值(进程 ID)来确定它是父进程还是子进程。
  • duppipe 返回的文件描述符,使用 int dup2(int oldfd, int newfd); 替换新进程的 stdinstdout
  • 使用exec* 函数之一在新进程中执行程序。

    // create pipes here
    
    if(pid_t pid = fork(); pid == -1) {
        // fork failed
    
    } else if(pid == 0) { // child process goes here (with a new process id)
        // dup2(...)
        // exec*()
    
    } else {              // parent process goes here
        // do parenting stuff
    }
    

例子:

#include <unistd.h>
#include <sys/types.h>

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <stdexcept>

struct Pipe {
    Pipe() {
        if(pipe(io)) throw std::runtime_error("pipe failure");
    }
    ~Pipe() {
        close_rd();
        close_wr();
    }
    void close_rd() { closer(io[0]); }
    void close_wr() { closer(io[1]); }
    int rd() { return io[0]; }
    int wr() { return io[1]; }

private:
    void closer(int& fd) {
        if(fd != -1) {
            close(fd);
            fd = -1;
        }
    }
    int io[2];
};

int main() {
    Pipe parent_write, parent_read;

    if(pid_t pid = fork(); pid == -1) {
        // fork failed
        return 1;

    } else if(pid == 0) {   // child process goes here (with a new process id)
        // close file descriptors we don't need:
        parent_write.close_wr();
        parent_read.close_rd();

        // duplicate into the place where stdin/stdout was
        dup2(parent_write.rd(), fileno(stdin));
        dup2(parent_read.wr(), fileno(stdout));

        // execute a program
        execl("/bin/ls", "/bin/ls", nullptr);
        // exec* functions never returns if successful, so if we get here, it failed:
        std::exit(1);

    } else {               // parent process goes here
        std::cout << "child process " << pid << " started\n";
    }

    // close file descriptors we don't need:
    parent_write.close_rd();
    parent_read.close_wr();

    // read data from child process using the file descriptor in parent_read.rd()
    char buf[1024];
    ssize_t rv;
    while((rv = read(parent_read.rd(), buf, 1024))) {
        write(fileno(stdout), buf, static_cast<size_t>(rv));
    }

    // use write(parent_write.wr(), ...) to write to the child.
}

【讨论】:

  • ... 或使用 posix_spawn,如 Jonathan Leffler 所述。 :-)
猜你喜欢
  • 1970-01-01
  • 2015-11-13
  • 2021-10-09
  • 1970-01-01
  • 2013-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-20
相关资源
最近更新 更多