2:一個更復(fù)雜的例子

我們在前面完成了一個基本的服務(wù)程序,但是這個程序還有很多不足
1、進(jìn)程執(zhí)行的時候占用當(dāng)前shell并且當(dāng)shell關(guān)閉時,服務(wù)進(jìn)程將會結(jié)束
2、進(jìn)程的退出依靠ctrl + c 來完成,這種強(qiáng)制結(jié)束的方式非常的不友好

我們將在下面著手修改這兩個問題
讓程序以demo的形勢運(yùn)行

#include <iostream>
#include <unistd.h>
using namespace std;
int main()
{
    cout <<"server is begin" << endl;

    daemon(1,0);
    while(true)
    {
        cout << "server is running..." << endl;

        sleep(1);
    }
    return 0;
}

執(zhí)行

[liujinchun@localhost test]$ ./server 
server is begin

這是我們發(fā)現(xiàn)當(dāng)輸出server is begin 之后,當(dāng)前的shell 并不會占用,我們用 ps x命令查看下進(jìn)程

[liujinchun@localhost test]$ ps x
   PID TTY      STAT   TIME COMMAND
 62373 ?        S      0:02 sshd: liujinchun@pts/2
 62374 pts/2    Ss     0:00 -bash
 69182 ?        Ss     0:00 ./server
 69443 pts/2    R+     0:00 ps x

我們看到 server進(jìn)程的tty 顯示為1個 ? 這個意思是server的進(jìn)程并不會占用任何一個tty

在這個新的程序中我們使用了一個新的函數(shù)daemon(1,0),我們來看下這個函數(shù)的參數(shù)意義

int daemon(int nochdir, int noclose);

參數(shù):

nochdir:當(dāng)此參數(shù)為0時,會更改創(chuàng)建出的danmon的執(zhí)行目錄為根目錄,否則(非0)時保持當(dāng)前執(zhí)行目錄不變。

noclose:當(dāng)次函數(shù)為0時,會將標(biāo)準(zhǔn)輸入(0),標(biāo)準(zhǔn)輸出(1),標(biāo)準(zhǔn)錯誤(2)重定向到/dev/null,否則保持原有標(biāo)準(zhǔn)輸入(0),標(biāo)準(zhǔn)輸出(1),標(biāo)準(zhǔn)錯誤(2)不變。

下面我們來結(jié)束程序

[liujinchun@localhost test]$ kill -2 69182
[liujinchun@localhost test]$ ps x
   PID TTY      STAT   TIME COMMAND
 62373 ?        S      0:02 sshd: liujinchun@pts/2
 62374 pts/2    Ss     0:00 -bash
 69560 pts/2    R+     0:00 ps x

通過kill命令向進(jìn)程發(fā)送一個ctrl+c結(jié)束信號,這時我們查看進(jìn)程已經(jīng)不在了

我們再次修改一下我們的程序

#include <iostream>
#include <unistd.h>
using namespace std;
int main()
{
    cout <<"server is begin" << endl;
    daemon(1,1);
    while(true)
    {
        cout << "server is running..." << endl;

        sleep(1);
    }

    cout <<"server is end" << endl;
    return 0;
}

修改一下 damon函數(shù)的第二個參數(shù),他會讓程序在當(dāng)前shell還沒有結(jié)束的時候依舊像當(dāng)前tty輸出數(shù)據(jù)
然后我們在程序的后面增加了一行話。
執(zhí)行程序我們會看到如下結(jié)果

[liujinchun@localhost test]$ ./server 
server is begin
[liujinchun@localhost test]$ server is running...
server is running...
server is running...
server is running...
server is running...
server is running...
server is running...
server is running...
server is running...
server is running...

程序已經(jīng)在向當(dāng)前的tty輸出。開啟一個新的shell窗口創(chuàng)建一個新的tty,并用kill命令向server進(jìn)程發(fā)送ctrl + c 信號。這時我們會看到程序并沒有打印出 server is end。這是因?yàn)?ctrl + c 會讓程序直接結(jié)束 。如果你想在服務(wù)進(jìn)程退出的時候進(jìn)程一些工作怎么辦呢。我們需要截獲這個信號并進(jìn)行自己的處理。

#include <iostream>
#include <unistd.h>
#include <signal.h>
using namespace std;

static bool run = true;
bool isRun()
{
    return run;
}

static void ctrlHandler( int signum )
{
    run = false;
}

int main()
{
    cout <<"server is begin" << endl;
    struct sigaction sig;
    sig.sa_handler = ctrlHandler;
    sigemptyset(&sig.sa_mask);
    sig.sa_flags = 0;
    sigaction(SIGINT,&sig,NULL);

    daemon(1,1);
    while(isRun())
    {
        cout << "server is running..." << endl;

        sleep(1);
    }

    cout <<"server is end" << endl;
    return 0;
}

運(yùn)行并發(fā)送kill信號

[liujinchun@localhost test]$ ./server 
server is begin
server is running...
[liujinchun@localhost test]$ server is running...
server is running...
server is running...
server is running...
server is running...
server is running...
server is running...
server is running...
server is running...
server is running...
server is end

我們看到程序執(zhí)行了退出命令

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容