1.概念
1.概念
后台进程:
守护进程:
最大的区别有几点:
(a)守护进程已经完全脱离终端控制台了,而后台程序并未完全脱离终端(在终端未关闭前还是会往终端输出结果);
(b)守护进程在关闭终端控制台时不会受影响,而后台程序会随用户退出而停止,需要在以nohup command & 格式运行才能避免影响;
(c)守护进程的会话组和当前目录,文件描述符都是独立的。后台运行只是终端进行了一次fork,让程序在后台执行,这些都没改变;
2.如何成为后台进程
2.如何成为后台进程
a.运行程序时,加&;例如:./test_app &
b.使用ctrl+z,bg等命令
3.如何成为守护进程
#include <unistd.h>
#include <errno.h>
#include <syslog.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#define CONFIG_DAEMON_ENABLE
#define LOCKFILE "/var/run/daemon.pid"
#define LOCKMODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
#ifdef CONFIG_DAEMON_ENABLE
static sigset_t mask;
void* signal_handle_pthread(void* arg)
{
int err, signo;
while(true)
{
err = sigwait(&mask, &signo);
if(err != 0)
{
syslog(LOG_ERR, "signal wait failed");
exit(1);
}
switch(signo)
{
case SIGHUP:
syslog(LOG_INFO, "Re-reading configuration file");
break;
case SIGTERM:
syslog(LOG_INFO, "got SIGTERM; exiting");
exit(0);
default:
syslog(LOG_INFO, "unexpected signal %d\n", signo);
}
}
/** add the thread detach attr */
pthread_detach(pthread_self());
}
void daemonize(const char* cmd)
{
int i,fd0, fd1, fd2;
pid_t pid;
struct rlimit r1;
struct sigaction sa;
/*clear file creation mask.*/
umask(0);
/*get maximum number of file descriptors.*/
if(getrlimit(RLIMIT_NOFILE, &r1) < 0)
fprintf(stderr, "%s: can't get file limit", cmd);
/*Become a session leader to loss controlling TTY*/
if((pid = fork()) < 0)
fprintf(stderr, "%s; can't fork", cmd);
else if(pid != 0) /*parent*/
exit(0);
setsid();
/*Ensure future opens won't allocate controlling TTYs.*/
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if(sigaction(SIGHUP, &sa, NULL) < 0)
fprintf(stderr, "%s:can't ignore SIGHUP", cmd);
if((pid = fork()) < 0)
fprintf(stderr, "%s; can't fork", cmd);
else if(pid != 0) /*parent*/
exit(0);
/*Change the current working directory to the root
* so we wong't prevent file systems from being unmounted.
*/
if(chdir("/") < 0)
fprintf(stderr, "%s; can't change directory to /", cmd);
/*close all open file descriptors.*/
if(r1.rlim_max == RLIM_INFINITY)
r1.rlim_max = 1024;
for(i=0; i<r1.rlim_max; i++)
{
close(i);
}
/*attach file descriptors 0, 1, and 2 to /dev/null.*/
fd0 = open("/dev/null", O_RDWR);
fd1 = dup(0);
fd2 = dup(0);
/*initialize the log file*/
openlog(cmd, LOG_CONS | LOG_PERROR, LOG_DAEMON);
if(fd0 != 0 || fd1 != 1 || fd2 != 2)
{
syslog(LOG_ERR, "unexpected file descriptors %d %d %d", fd0, fd1, fd2);
exit(1);
}
syslog(LOG_NOTICE, "become a daemon ... Build Date: "__DATE__" "__TIME__"");
}
static int daemon_lockfile(int fd)
{
struct flock file_lock;
file_lock.l_type = F_WRLCK;
file_lock.l_start = 0;
file_lock.l_whence = SEEK_SET;
file_lock.l_len = 0;
return fcntl(fd, F_SETLK, &file_lock);
}
static int daemon_already_running(void)
{
int fd;
char buf[16];
fd = open(LOCKFILE, O_RDWR | O_CREAT, LOCKMODE);
if(fd < 0)
{
syslog(LOG_ERR, "can't open %s: %s", LOCKFILE, strerror(errno));
exit(1);
}
if(daemon_lockfile(fd) < 0)
{
if(errno == EACCES || errno == EAGAIN)
{
close(fd);
return (1);
}
syslog(LOG_ERR, "cat't lock %s: %s", LOCKFILE, strerror(errno));
exit(1);
}
ftruncate(fd, 0);
sprintf(buf, "%ld", (long)getpid());
write(fd, buf, strlen(buf)+1);
return 0;
}
#endif
int main(int argc, char* argv[])
{
#ifdef CONFIG_DAEMON_ENABLE
int err;
pthread_t tid;
char *cmd;
struct sigaction sa;
if((cmd = strrchr(argv[0], '/')) == NULL)
cmd = argv[0];
else
cmd ++;
/*become a daemon.*/
daemonize(cmd);
fprintf(stderr, "become a daemon.....\n");
/*make sure only one copy of the daemon is running.*/
if(daemon_already_running())
{
syslog(LOG_ERR, "daemon already running");
fprintf(stderr, "daemon already running\n");
exit(1);
}
/*Restore SIGHUP default and block all signals.*/
sa.sa_handler = SIG_DFL;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if(sigaction(SIGHUP, &sa, NULL) < 0)
syslog(LOG_ERR, "can't restore SIGHUP default");
sigfillset(&mask);
if((err = pthread_sigmask(SIG_BLOCK, &mask, NULL)) != 0)
{
syslog(LOG_ERR, "SIG_BLOCK error");
exit(1);
}
/*create a thread to handle SIGHUP and SIGTERM.*/
if((err = pthread_create(&tid, NULL, signal_handle_pthread, 0)) !=0 )
{
syslog(LOG_ERR, "can't create thread");
exit(1);
}
#endif
syslog(LOG_NOTICE,"add your application \r\n");
#if 1
while(1)
{
syslog(LOG_NOTICE,"....\r\n");
printf("....\r\n");
sleep(2);
}
#endif
/*TODO*/
return 0;
}
4.与系统任务相关的命令
命令:ctrl+z,ctrl+c,fg,bg,jobs,&
参考:
http://www.cnblogs.com/z-sm/p/5675051.html
http://www.cnblogs.com/boodoog/p/6043083.html
http://blog.csdn.net/daiyudong2020/article/details/50810564
linux之dup和dup2函数解析:http://blog.csdn.net/fulinus/article/details/9669177
NOTE:int dup(int oldfd);
/*int newfd = dup(oldfd);//新文件描述符newfd指向oldfd文件描述符所拥有的文件
*/