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条回答
ゆ 、 Hurt°
2楼-- · 2020-02-05 02:59

On Linux, daemon() is what you're looking for, if I understand you correctly.

查看更多
地球回转人心会变
3楼-- · 2020-02-05 03:00

The most common way of doing this under Linux is via forking. The same should work on Mac, as for Windows I'm not 100% sure but I believe they have something similar.

Basically what happens is the process splits itself into two processes, and then the original one exits (returning control to the shell or whatever), and the second process continues to run in the background.

查看更多
冷血范
4楼-- · 2020-02-05 03:01
/**Deamonize*/

pid_t pid;
pid = fork(); /**father makes a little deamon(son)*/
if(pid>0)
exit(0); /**father dies*/
while(1){
printf("Hello I'm your little deamon %d\n",pid); /**The child deamon goes on*/
sleep(1)
}

/** try 'nohup' in linux(usage: nohup <command> &) */
查看更多
甜甜的少女心
5楼-- · 2020-02-05 03:02

The simplest form of backgrounding is:

if (fork() != 0) exit(0);

In Unix, if you want to background an disassociate from the tty completely, you would do:

  1. Close all descriptors which may access a tty (usually 0, 1, and 2).
  2. if (fork() != 0) exit(0);
  3. setpgroup(0,getpid()); /* Might be necessary to prevent a SIGHUP on shell exit. */
  4. signal(SIGHUP,SIG_IGN); /* just in case, same as using nohup to launch program. */
  5. fd=open("/dev/tty",O_RDWR);
  6. ioctl(fd,TIOCNOTTY,0); /* Disassociates from the terminal */
  7. close(fd);
  8. if (fork() != 0) exit(0); /* just for good measure */

That should fully daemonize your program.

查看更多
Juvenile、少年°
6楼-- · 2020-02-05 03:06

Here is some pseudocode for Linux/UNIX:

initialization_code()
if(failure) exit(1)
if( fork() > 0 ) exit(0)
setsid()
setup_signal_handlers()
for(fd=0; fd<NOFILE; fd++) close(fd)
open("/dev/null", O_RDONLY)
open("/dev/null", O_WRONLY)
open("/dev/null", o_WRONLY)
chdir("/")

And congratulations, your program continues as an independent "daemonized" process without a controlling TTY and without any standard input or output.

Now, in Windows you simply build your program as a Win32 application with WinMain() instead of main(), and it runs without a console automatically. If you want to run as a service, you'll have to look that up because I've never written one and I don't really know how they work.

查看更多
Melony?
7楼-- · 2020-02-05 03:07

To followup on your edited question:

I was wondering if there was a way to put the EXISTING process into the background.

In a Unix-like OS, there really is not a way to do this that I know of. The shell is blocked because it is executing one of the variants of a wait() call, waiting for the child process to exit. There is not a way for the child process to remain running but somehow cause the shell's wait() to return with a "please stop watching me" status. The reason you have the child fork and exit the original is so the shell will return from wait().

查看更多
登录 后发表回答