看到一篇英文的
from:
http://www.ucdot.org/article.pl?sid=03/12/...219&mode=threadSometimes it is useful to start an application which is backgrounded and no longer associated with the starting terminal. Usually this is referred to as daemonizing.
Stevens in his book "Advanced programming in the unix environment" presents the classic daemonizing code. I have modified it here to create an application which when run from the command line, detaches from the command line and writes a message to syslog every 5 seconds.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <syslog.h>
int main(int argc, char *argv[])
{
char c;
int _argc = 0;
char *_argv[3];
pid_t pid;
if ((pid = fork()) < 0) {
fprintf(stderr, "fork failed\n");
exit(1);
} else if (pid != 0) {
exit(0);
}
setsid();
chdir("/");
umask(0);
close(0);
close(1);
close(2);
for (;;) {
sleep(5);
syslog(LOG_INFO, "Still sleeping\n");
}
}
The trouble with the above is that it doesn't work under uClinux because there is no fork, only vfork. If we replace the fork call above with vfork, then the parent application never terminates. The child won't background until exec is called.
We can thus modify the classic daemonizing program to exec a program which can then be the background process while the parent process terminates. The trick is to exec the original program itself with an argument which indicates that it is the child process. The code below illustrates.
/*
* © Matthew Natalier, 2003
*
* If you want to use this, tell me that you love me :-)
*
*/
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <sys/types.h>
#include <unistd.h>
int execed = 0;
int main(int argc, char *argv[])
{
char c;
int _argc = 0;
char *_argv[3];
pid_t pid;
while ((c=getopt(argc, argv, "D")) > 0) {
switch© {
case 'D':
execed = 1;
break;
default:
fprintf(stderr, "You probably don't want to pass "
"options to this\n");
exit(1);
}
}
if (!execed) {
if ((pid = vfork()) < 0) {
fprintf(stderr, "vfork failed\n");
exit(1);
} else if (pid != 0) {
exit(0);
}
_argv[_argc++] = argv[0];
_argv[_argc++] = "-D";
_argv[_argc++] = NULL;
execv(_argv[0], _argv);
/* Not reached */
fprintf(stderr, "Couldn't exec\n");
_exit(1);
} else {
setsid();
chdir("/");
umask(0);
close(0);
close(1);
close(2);
}
for (;;) {
sleep(5);
syslog(LOG_INFO, "Still sleeping\n");
}
}
The best thing about the above code is that it will work on uClinux or standard Linux systems without modification.