相信隨著Linux的普及,大家都在寫不少Linux下的程序了,尤其是一些服務端程序慢慢地都轉到Linux下了吧。大家必然碰到問題是如何讓自己的進程成為守護進程,在系統啟動的時候運行,並且永遠是後台進程。下面就寫一個這樣的程序了。源代碼如下:
//////////////////////////////init_daemon.c 開始///////////////////////////////////////////
#include
#include
#include
#include
#include
/*********************************************************************
*filename: init_daemon.c
*purpose: 產生後台進程
*wrote by: zhoulifa 周立發
*date time:2006-03-10 01:00:00
*Thanks to: 北京工業大學 小胡
)
*Note: 任何人可以任意復制代碼並運用這些代碼,當然包括你的商業用途
* 但請遵循GPL
*********************************************************************/
void init_daemon(void)
{
int pid;
int i;
if(pid=fork())
exit(0);//是父進程,結束父進程
else if(pid< 0)
exit(1);//fork失敗,退出
//是第一子進程,後台繼續執行
setsid();//第一子進程成為新的會話組長和進程組長
//並與控制終端分離
if(pid=fork())
exit(0);//是第一子進程,結束第一子進程
else if(pid< 0)
exit(1);//fork失敗,退出
//是第二子進程,繼續
//第二子進程不再是會話組長
for(i=0;i< NOFILE;++i)//關閉打開的文件描述符
close(i);
chdir("/tmp");//改變工作目錄到/tmp
umask(0);//重設文件創建掩模
return;
}
//////////////////////////////init_daemon.c 結束///////////////////////////////////////////
上面這是個通用的函數,可以讓你的程序成為後台守護進程。
下面是一個測試程序:
//////////////////////////////daemontest.c 開始///////////////////////////////////////////
#include
#include
/*********************************************************************
*filename: daemontest.c
*purpose: 測試後台進程
*wrote by: zhoulifa周立發
*date time:2006-03-10 01:09:00
*Thanks to: 北京工業大學 小胡
*Note: 任何人可以任意復制代碼並運用這些代碼,當然包括你的商業用途
* 但請遵循GPL
*********************************************************************/
void init_daemon(void);//守護進程初始化函數
void signal_reload(int signal)
{
/*當收到SIGUSR1信號時程序重新導入所有參數*/
FILE *fp;
time_t t;
if((fp=fopen("test.log","a")) >=0)
{
t=time(0);
fprintf(fp,"I received signal(%d), reload all parameters at %s\n", signal, asctime(localtime(&t)) );
fclose(fp);
}
/*重新導入參數*/
}
void signal_handle(int signal)
{
/*當收到SIGUSR2信號時程序退出*/
FILE *fp;
time_t t;
if((fp=fopen("test.log","a")) >=0)
{
t=time(0);
fprintf(fp,"I received signal(%d), exit at %s\n", signal, asctime(localtime(&t)) );
fclose(fp);
}
exit(0);
}
int main(int argc, char ** argv)
{
FILE *fp;
time_t t;
init_daemon();//初始化為Daemon
signal(SIGCHLD, SIG_IGN);/*忽略子進程退出信號,若在此之後又產生了子進程,
如果不處理此信號,將在子進程退出後產生僵屍進程*/
signal(SIGUSR1, signal_reload);/*處理SIGUSR1信號,可以定義此信號為重導參數信號*/
signal(SIGUSR2, signal_handle);/*處理SIGUSR2信號,可以定義此信號為退出信號*/
while(1)//每隔一分鐘向test.log報告運行狀態
{
/*這是各位程序的主體部分,所以的工作在下面完成,比如http服務、FTP服務等*/
sleep(60);//睡眠一分鐘
if((fp=fopen("test.log","a")) >=0)/*注意,由於在init_daemon裡面已經把路徑切換到了/tmp,因此此文件是/tmp/test.log*/
{
t=time(0);
fprintf(fp,"I'm here at %s\n",asctime(localtime(&t)) );
fclose(fp);
}
}
}
//////////////////////////////daemontest.c 結束///////////////////////////////////////////
編譯時使用命令進行聯合編譯:
gcc init_daemon.c daemontest.c
產生了一個程序比如叫a.out
你就可以運行此程序了。/a.out了。
如果想要此程序在系統啟動時自動運行,你可以在/etc/rc.d/rc.local裡面用su命令加上一行,比如:
su - Jacky -c "/bin/a.out"
這個命令將以Jacky用戶身份運行/bin/a.out程序
程序運行過程中如果你修改了程序的參數,則必然希望程序重新導入參數,那麼你可以用ps命令查看程序的進程號:
ps -ef|grep a.out
然後用kill命令向程序發參數,比如:
kill -s SIGUSR1 11422
同理,如果想要終止程序,則向程序發SIGUSR2信號:
kill -s SIGUSR2 11422