Bạn không thể tạo một tiến trình trong linux mà không thể bị giết. Người dùng root (uid = 0) có thể gửi tín hiệu đến một tiến trình và có hai tín hiệu không thể bắt được, SIGKILL = 9, SIGSTOP = 19. Và các tín hiệu khác (khi chưa được ghi nhớ) cũng có thể dẫn đến kết thúc quá trình.
Bạn có thể muốn một hàm daemonize tổng quát hơn, nơi bạn có thể chỉ định tên cho chương trình / daemon của mình và đường dẫn để chạy chương trình của bạn (có thể là "/" hoặc "/ tmp"). Bạn cũng có thể muốn cung cấp (các) tệp cho stderr và stdout (và có thể là một đường dẫn điều khiển sử dụng stdin).
Dưới đây là những thứ cần thiết bao gồm:
#include <stdio.h> //printf(3)
#include <stdlib.h> //exit(3)
#include <unistd.h> //fork(3), chdir(3), sysconf(3)
#include <signal.h> //signal(3)
#include <sys/stat.h> //umask(3)
#include <syslog.h> //syslog(3), openlog(3), closelog(3)
Và đây là một chức năng tổng quát hơn,
int
daemonize(char* name, char* path, char* outfile, char* errfile, char* infile )
{
if(!path) { path="/"; }
if(!name) { name="medaemon"; }
if(!infile) { infile="/dev/null"; }
if(!outfile) { outfile="/dev/null"; }
if(!errfile) { errfile="/dev/null"; }
//printf("%s %s %s %s\n",name,path,outfile,infile);
pid_t child;
//fork, detach from process group leader
if( (child=fork())<0 ) { //failed fork
fprintf(stderr,"error: failed fork\n");
exit(EXIT_FAILURE);
}
if (child>0) { //parent
exit(EXIT_SUCCESS);
}
if( setsid()<0 ) { //failed to become session leader
fprintf(stderr,"error: failed setsid\n");
exit(EXIT_FAILURE);
}
//catch/ignore signals
signal(SIGCHLD,SIG_IGN);
signal(SIGHUP,SIG_IGN);
//fork second time
if ( (child=fork())<0) { //failed fork
fprintf(stderr,"error: failed fork\n");
exit(EXIT_FAILURE);
}
if( child>0 ) { //parent
exit(EXIT_SUCCESS);
}
//new file permissions
umask(0);
//change to path directory
chdir(path);
//Close all open file descriptors
int fd;
for( fd=sysconf(_SC_OPEN_MAX); fd>0; --fd )
{
close(fd);
}
//reopen stdin, stdout, stderr
stdin=fopen(infile,"r"); //fd=0
stdout=fopen(outfile,"w+"); //fd=1
stderr=fopen(errfile,"w+"); //fd=2
//open syslog
openlog(name,LOG_PID,LOG_DAEMON);
return(0);
}
Đây là một chương trình mẫu, nó sẽ trở thành một daemon, treo xung quanh và sau đó rời đi.
int
main()
{
int res;
int ttl=120;
int delay=5;
if( (res=daemonize("mydaemon","/tmp",NULL,NULL,NULL)) != 0 ) {
fprintf(stderr,"error: daemonize failed\n");
exit(EXIT_FAILURE);
}
while( ttl>0 ) {
//daemon code here
syslog(LOG_NOTICE,"daemon ttl %d",ttl);
sleep(delay);
ttl-=delay;
}
syslog(LOG_NOTICE,"daemon ttl expired");
closelog();
return(EXIT_SUCCESS);
}
Lưu ý rằng SIG_IGN chỉ ra để bắt và bỏ qua tín hiệu. Bạn có thể xây dựng một trình xử lý tín hiệu có thể ghi lại quá trình nhận tín hiệu và đặt các cờ (chẳng hạn như cờ để chỉ báo tắt máy nhanh).