Derf Skren
Derf Skren

Reputation: 509

Linux equivalent of Process.Start()

On Windows in C#, I can launch an external program from within my code by calling Process.Start(), which starts the process and returns its ID. This is important because I am not forking my own process, and I might have to kill the process later.

I have looked at exec(), fork() and many other things under Linux in C++ but none of those do quite the same thing. For example, system() blocks while the program runs, and fork() duplicates my whole process just so I can run another task.

Can someone tell me what the equivalent is?

Upvotes: 0

Views: 1162

Answers (3)

Jesper Juhl
Jesper Juhl

Reputation: 31447

The way to start a new process on Linux is by using fork and exec. This you can wrap in your own System class that holds the PID and provides methods to kill the process etc. An example of such a class is QProcess from the Qt library.

Note: there's also the posix_spawn() and (Linux specific) clone() functions.

Upvotes: 1

Derf Skren
Derf Skren

Reputation: 509

Thanks to @user4581301 for the comment above. posix_spawn() was what I was looking for.

Here is the code I ended up using though.

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

class ProcessCancelHelper {
 private:
  pid_t process_id_;

 public:
  ProcessCancelHelper()
  : process_id_(0) {}

  int StartProcess(const char* command_buffer) {
    const char* command_argv[4];
    command_argv[0] = "sh";
    command_argv[1] = "-c";
    command_argv[2] = command_buffer;
    command_argv[3] = nullptr;

    process_id_ = fork();
    if (process_id_ == -1) return -1;
    if (process_id_ == 0) {
      execvp(command_argv[0], const_cast<char* const*>(command_argv));
      assert(false && "execvp did not work");
      exit(-1);
    }

    int wait_status;
    if (waitpid(process_id_, &wait_status, 0))
    {
      process_id_ = 0;
      if (WIFEXITED(wait_status)) return (WEXITSTATUS(wait_status));
      return -1;
    }

    process_id_ = 0;
    return -1;
  }

  bool CancelProcess() {
    return (process_id_ != 0 && kill(process_id_, SIGKILL) == 0);
  }
}

This works and I have not yet tried switching to using posix_spawn instead, but as discussed that is just a wrapper.

Upvotes: 0

ivan.ukr
ivan.ukr

Reputation: 3551

There is no equivalent. This is difference between Windows and Linux (and any other Unix-like system). In Unix-like system, new process is always started using fork() + exec(). Higher level C library APIs like system() use fork() + exec() system calls under the hood, because there is absolutely no other way. But Windows always creates new process from scratch. But you should not be discouraged by the fact that fork() creates copy of the current process. In fact it does it in a very specific way, so that actually almost nothing copied until write to memory occurs. And even in this case, only modified memory page is copied. Otherwise, creating new processes on Unix/Linux would be over-expensive (for example, assume a process which consumes 4GB of memory wants to execute some shell command). And in fact, exec() does the job which CreateProcess() does on Windows - assigns new executable image to process, re-initializes heap and stack.

Upvotes: 1

Related Questions