linux下daemon進程模板

來源:互聯網
上載者:User

    平時經常性會需要寫一些daemon服務,於是就寫了一個簡單的指令碼,利用模板檔案,可以自動產生一個簡單的daemon進程,包括源檔案和makefile,啟停指令碼,只需要直接添上商務邏輯即可。使用方式:./generate_daemon.sh <app name>。

    工具的在這裡: http://download.csdn.net/source/3242136

    執行./generate_daemon.sh test,產生的目錄結構如下,包括src,bin和etc目錄和一個Makefile。

   

 

    下面簡單介紹一下產生的程式碼,大概有幾點說明一下:

(1)daemon進程的上下文資料結構中,包括自己的pid,以及pid檔案的path;另外有一個stop標誌來控制進程的起停;

(2)每一個daemon進程都應該有自己的id號。編譯之後的啟停方式,應該類似這樣:

    ./test --id=192.0.0.1 --daemon start

    ./test --id=192.0.0.1 stop

(2)version參數可以看到版本號碼,這裡也就是編譯的時間;help可以顯示使用說明。

(3)進程第一次啟動時,會將自己的pid寫入一個檔案,目前這個檔案在tmp目錄下,為進程名字+id號,寫完之後會加鎖。在stop進程時,會去讀這個檔案,併到/proc/pid目錄下驗證進程名字;如果start進程時,發現這個pid檔案已經存在,會提示錯誤。-->如果想起多個進程,必須用不同的id來控制;

(4)stop進程,是用發送kill訊號的方式來實現的,目前捕捉的訊號包括SIGINT,SIGUSR1,SIGKILL,SIGQUIT;

(5)正常情況下,進程將死迴圈執行process函數,加上需要的商務邏輯即可。

(6)產生一個test進程,make之後啟動指令碼,可以看到進程正常運行ing:

 

    最後把部分代碼貼出來:

 

    /*<br /> * @author: auther <auther mail><br /> * @date: 2011-05-02<br /> * @function: test daemon server header<br />*/<br />....<br />// test daemon server contxt<br />typedef struct TESTContext<br />{<br />intpid;<br />charpid_file[256];<br />charid[16];<br />boolis_stop;<br />bool is_daemon;<br />time_tcurrent_time;<br />}TESTCtx;<br />int test_init();<br />int test_finish();<br />int test_daemonize();<br />int test_signal_init();<br />void test_signal_handler(int);<br />int test_process();<br />int test_tick();<br />int test_help();<br />int test_write_pid(const char*);</p><p>int test_read_pid(const char*);<br />int test_is_exist();<br />int test_kill();<br />....   

    /*<br /> * @author: auther <auther mail><br /> * @date: 2011-05-02<br /> * @function: test daemon server source<br />*/<br />#include "test.h"<br />TESTCtx* gSvrdCtx = NULL;<br />inttest_init()<br />{<br />gSvrdCtx = (TESTCtx*)malloc(sizeof(TESTCtx));</p><p>if(!gSvrdCtx)<br />{<br />fprintf(stderr, "malloc server context fail, no free memory../n");<br />return -1;<br />}</p><p>memset(gSvrdCtx, 0, sizeof(TESTCtx));<br />gSvrdCtx->current_time = time(NULL);<br />gSvrdCtx->is_stop = false;<br />gSvrdCtx->is_daemon = false;<br />// TODO: </p><p>return 0;<br />}<br />int test_finish()<br />{<br />// TODO: </p><p>free(gSvrdCtx);<br />return 0;<br />}<br />int test_process()<br />{<br />// TODO:</p><p>return -1;<br />}<br />int test_tick()<br />{<br />// TODO:<br />return -1;<br />}<br />int test_daemonize()<br />{<br /> signal(SIGTTOU, SIG_IGN);<br /> signal(SIGTTIN, SIG_IGN);<br /> signal(SIGTSTP, SIG_IGN);<br /> int i,pid;<br /> if((pid = fork()))<br /> {<br /> exit(0);<br /> }<br /> else if(pid < 0)<br /> {<br /> exit(1);<br /> }<br /> setsid();</p><p> signal( SIGHUP, SIG_IGN );<br /> if((pid = fork()))<br /> {<br />exit(0);<br /> }<br /> else if(pid < 0)<br /> {<br /> exit(1);<br /> }</p><p> for(i =0; i < 255; i++)<br /> {<br />close(i);<br /> }</p><p> umask(0);<br /> return 0;<br />}<br />int test_signal_init()<br />{<br />struct sigaction act;<br />act.sa_handler = SIG_IGN;<br />sigaction(SIGTERM, &act, NULL);<br />sigaction(SIGPIPE, &act, NULL);<br />sigaction(SIGHUP, &act, NULL);<br />sigaction(SIGCHLD, &act, NULL);<br />sigaction(SIGALRM, &act, NULL);</p><p>act.sa_handler = test_signal_handler;<br />sigemptyset(&act.sa_mask);<br />act.sa_flags = 0;<br />sigaction(SIGINT, &act, NULL);<br />return 0;<br />}<br />void test_signal_handler(int signal)<br />{<br />if(SIGINT == signal//ctrl + c, kill -2<br />|| SIGUSR1 == signal// quit, kill -10<br />|| SIGKILL == signal// kill -9<br />|| SIGQUIT == signal)// kill -3<br />{<br />fprintf(stderr, "catch signal SIGINT, server shutdown/n");<br />gSvrdCtx->is_stop = true;<br />}<br />}<br />int test_help()<br />{<br />const char* szHelpInfo = "test start-up parameters: /n"/<br />"--id /n"/<br />"--daemaon /n"/<br />"--help /n"/<br />"--version /n"/<br />"[start | stop] /n";<br />fprintf(stderr, szHelpInfo);<br />return 0;<br />}<br />int test_write_pid(const char* szPidFile)<br />{<br />if(!szPidFile)<br />{<br />fprintf(stderr, "no pid file to write!/n");<br />return -1;<br />}</p><p>int fd = open(szPidFile, O_CREAT | O_TRUNC | O_RDWR, 0666);<br />if(fd < 0)<br />{<br />fprintf(stderr, "open(create) pid file[%s] fail!/n", szPidFile);<br />return -1;<br />}<br />// lock pid file<br />if(0 != flock(fd, LOCK_EX | LOCK_NB))<br />{<br />fprintf(stderr, "lock to pid file[%s] fail!/n", szPidFile);<br />close(fd);<br />return -1;<br />}<br />char szPid[16];<br />memset(szPid, 0, 16);<br />snprintf(szPid, 16, "%d", gSvrdCtx->pid);<br />int len = strlen(szPid);<br />if(len != write(fd, szPid, len))<br />{<br />fprintf(stderr, "write pid file[%s] fail!/n", szPidFile);<br />close(fd);<br />return -1;<br />}</p><p>close(fd);<br />return 0;<br />}</p><p>int test_read_pid(const char* szPidFile)<br />{<br />if(!szPidFile)<br />{<br />fprintf(stderr, "no pid file to read!/n");<br />return -1;<br />}</p><p>int fd = open(szPidFile, O_RDONLY, 0644);<br />if(fd < 0)<br />{<br />return -1;<br />}<br />char szPid[16];<br />memset(szPid, 0, 16);<br />if(-1 == read(fd, szPid, sizeof(szPid)))<br />{<br />fprintf(stderr, "read pid file[%s] fail!/n", szPidFile);<br />close(fd);<br />return -1;<br />}<br />int pid = atoi(szPid);<br />close(fd);<br />return pid;<br />}<br />// return 1, exist<br />// return 0, not exist<br />// return -1, check fail<br />int test_is_exist()<br />{<br />if(!gSvrdCtx || !gSvrdCtx->pid_file)<br />{<br />fprintf(stderr, "invalid test context!/n");<br />return -1;<br />}<br />int pid = test_read_pid(gSvrdCtx->pid_file);</p><p>// no pid read, then not existed<br />if(pid < 0)<br />{<br />return 0;<br />}<br />char szProcDir[256];<br />memset(szProcDir, 0, sizeof(szProcDir));<br />snprintf(szProcDir, 256, "/proc/%d", pid);<br />// check whether process existed in /proc<br />struct stat stStat;<br />int ret = stat(szProcDir, &stStat);<br />if(ret < 0 || !S_ISDIR(stStat.st_mode))<br />{<br />return 0;<br />}<br />// check process name whether equals to test<br />snprintf(szProcDir, 256, "/proc/%d/status", pid);<br />FILE* fd = fopen(szProcDir, "r");<br />if(fd)<br />{<br />char buff[64];<br />char name_str[64];<br />memset(name_str, 0, sizeof(name_str));<br />memset(buff, 0, sizeof(buff));</p><p>// read first line("Name")<br />if(NULL != fgets(buff, sizeof(buff), fd))<br />{<br />// dest name found<br />sscanf(buff, "%*s %s", name_str);<br />if (0 == strcmp(name_str, "test"))<br />{<br />fclose(fd);<br />return 1;<br />}<br />}<br />fclose(fd);<br />}<br />return 0;<br />}<br />int test_kill()<br />{<br />if(!gSvrdCtx || !gSvrdCtx->pid_file)<br />{<br />fprintf(stderr, "invalid test context!/n");<br />return -1;<br />}<br />int ret = -1;<br />if(test_is_exist() > 0)<br />{<br />int pid = test_read_pid(gSvrdCtx->pid_file);<br />ret = kill(pid, SIGINT);<br />}<br />// delete pid file<br />unlink(gSvrdCtx->pid_file);<br />return ret;<br />}<br />int main(int argc, char* argv[])<br />{<br />if(test_init() < 0)<br />{<br />fprintf(stderr, "test server init fail/n");<br />return -1;<br />}<br />// load main parameters<br />static struct option szLongOptions[] =<br />{<br />{"id",1,NULL,'d'},<br />{"daemon",0,NULL,'D'},<br />{"help",0,NULL,'H'},<br />{"version",0,NULL,'V'},<br />{0, 0,0,0}<br />};<br />int ch;<br />while((ch = getopt_long(argc,<br />argv,<br />"d:h:v",<br />szLongOptions,<br />NULL)) != EOF)<br />{<br />switch(ch)<br />{<br />case 'd':<br />snprintf(gSvrdCtx->id, 16, "%s", optarg);<br />snprintf(gSvrdCtx->pid_file, 256, "/tmp/test_%s.pid", optarg);<br />break;</p><p>case 'D':<br />gSvrdCtx->is_daemon = true;<br />break;</p><p>case 'H':<br />test_help();<br />free(gSvrdCtx);<br />exit(0);<br />case 'V':<br />fprintf(stderr,"test compile at %s %s/n", __DATE__, __TIME__);<br />free(gSvrdCtx);<br />exit(0);<br />}<br />}<br />if(optind >= argc)<br />{<br />test_help();<br />free(gSvrdCtx);<br />exit(0);<br />}</p><p>for (int opt = optind; opt < argc; opt++)<br />{<br />if (0 == strcasecmp(argv[opt], "start"))<br />{<br />// if process already exsit, then warning & exit<br />if(test_is_exist() > 0)<br />{<br />fprintf(stderr, "test server %s already started. /n",<br />gSvrdCtx->id);<br />free(gSvrdCtx);<br />exit(0);<br />}</p><p>fprintf(stderr, "test server start. /n");<br />break;<br />}<br />else if (0 == strcasecmp(argv[opt], "stop"))<br />{<br />fprintf(stderr, "test server stop. /n");<br />// if process not exsit, then warning & exit<br />if(test_is_exist() <= 0)<br />{<br />fprintf(stderr, "test server %s not started. /n",<br />gSvrdCtx->id);<br />}<br />// kill previous process<br />else if(test_kill() < 0)<br />{<br />fprintf(stderr, "kill previous test server %s fail. /n",<br />gSvrdCtx->id);<br />}<br />else<br />{<br />fprintf(stderr, "kill previous test server %s success. /n",<br />gSvrdCtx->id);<br />}</p><p>free(gSvrdCtx);<br />exit(0);<br />}<br />else<br />{<br />test_help();<br />free(gSvrdCtx);<br />exit(0);<br />}<br />}</p><p>fprintf(stderr, "init test server success!/n");<br />if(gSvrdCtx->is_daemon)<br />{<br />test_daemonize();<br />}<br />gSvrdCtx->pid = getpid();<br />if(test_write_pid(gSvrdCtx->pid_file) < 0)<br />{<br />fprintf(stderr, "test server %s init fail. /n",<br />gSvrdCtx->id);<br />free(gSvrdCtx);<br />exit(0);<br />}</p><p>while(!gSvrdCtx->is_stop)<br /> {<br /> gSvrdCtx->current_time = time(NULL);</p><p> if(test_process() < 0)<br /> {<br /> usleep(100);<br /> }</p><p> test_tick();<br /> }</p><p> test_finish();</p><p>fprintf(stderr, "test server is exit/n");</p><p>return 0;<br />}</p><p>

   

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.