How can a C/C++ program put itself into background

2020-02-05 02:29发布

What's the best way for a running C or C++ program that's been launched from the command line to put itself into the background, equivalent to if the user had launched from the unix shell with '&' at the end of the command? (But the user didn't.) It's a GUI app and doesn't need any shell I/O, so there's no reason to tie up the shell after launch. But I want a shell command launch to be auto-backgrounded without the '&' (or on Windows).

Ideally, I want a solution that would work on any of Linux, OS X, and Windows. (Or separate solutions that I can select with #ifdef.) It's ok to assume that this should be done right at the beginning of execution, as opposed to somewhere in the middle.

One solution is to have the main program be a script that launches the real binary, carefully putting it into the background. But it seems unsatisfying to need these coupled shell/binary pairs.

Another solution is to immediately launch another executed version (with 'system' or CreateProcess), with the same command line arguments, but putting the child in the background and then having the parent exit. But this seems clunky compared to the process putting itself into background.

Edited after a few answers: Yes, a fork() (or system(), or CreateProcess on Windows) is one way to sort of do this, that I hinted at in my original question. But all of these solutions make a SECOND process that is backgrounded, and then terminate the original process. I was wondering if there was a way to put the EXISTING process into the background. One difference is that if the app was launched from a script that recorded its process id (perhaps for later killing or other purpose), the newly forked or created process will have a different id and so will not be controllable by any launching script, if you see what I'm getting at.

Edit #2:

fork() isn't a good solution for OS X, where the man page for 'fork' says that it's unsafe if certain frameworks or libraries are being used. I tried it, and my app complains loudly at runtime: "The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec()."

I was intrigued by daemon(), but when I tried it on OS X, it gave the same error message, so I assume that it's just a fancy wrapper for fork() and has the same restrictions.

Excuse the OS X centrism, it just happens to be the system in front of me at the moment. But I am indeed looking for a solution to all three platforms.

20条回答
We Are One
2楼-- · 2020-02-05 03:16

A process cannot put itself into the background, because it isn't the one in charge of background vs. foreground. That would be the shell, which is waiting for process exit. If you launch a process with an ampersand "&" at the end, then the shell does not wait for process exit.

But the only way the process can escape the shell is to fork off another child and then let its original self exit back to the waiting shell.

From the shell, you can background a process with Control-Z, then type "bg".

查看更多
SAY GOODBYE
3楼-- · 2020-02-05 03:16

I'm not sure about Windows, but on UNIX-like systems, you can fork() then setsid() the forked process to move it into a new process group that is not connected to a terminal.

查看更多
欢心
4楼-- · 2020-02-05 03:18

Under Windows, the closing thing you're going to get to fork() is loading your program as a Windows service, I think.

Here is a link to an intro article on Windows services... CodeProject: Simple Windows Service Sample

查看更多
干净又极端
5楼-- · 2020-02-05 03:19

On UNIX, you need to fork twice in a row and let the parent die.

查看更多
ゆ 、 Hurt°
6楼-- · 2020-02-05 03:21

Three things need doing,

fork
setsid
redirect STDIN, STDOUT and STDERR to /dev/null

This applies to POSIX systems (all the ones you mention claim to be POSIX (but Windows stops at the claiming bit))

查看更多
Summer. ? 凉城
7楼-- · 2020-02-05 03:21

As others mentioned, fork() is how to do it on *nix. You can get fork() on Windows by using MingW or Cygwin libraries. But those will require you to switch to using GCC as your compiler.

In pure Windows world, you'd use CreateProcess (or one of its derivatives CreateProcessAsUser, CreateProcessWithLogonW).

查看更多
登录 后发表回答