1. 程式人生 > >為程序建立新會話-----setsid()-舉例,精靈程序

為程序建立新會話-----setsid()-舉例,精靈程序

#include <unistd.h>
pid_t setsid(void);
    描述:如果呼叫該系統呼叫的程序不是其程序組的組長則會建立一個新的會話。呼叫程序將會稱為新會話的組長,會話id和其pid一致。也成為新會話中新的程序組的組長,程序組的id和其pid保持一致。呼叫程序是新程序組和新會話中唯一的程序,新的會話將會脫離終端的控制。
    引數:無
    返回值:
        成功:呼叫程序的pid將會返回
        失敗:-1被返回,errno被設定。

基於上述系統呼叫,我們可以將一個bash下的子程序變成一個精靈程序,使其不受終端控制。
在終端啟動的程序,首先程序繼承了終端的會話id和程序組id,其次程序繼承了終端的檔案描述符(STDIN_FILENO,STDOUT_FILENO,STDERR_FILENO),所以使用setsid()僅能改變程序的會話id和程序組id,卻不能刪除其繼承到的檔案描述符。在這種情況下,如果原終端沒有關閉,那麼程序將會在終端裡輸出。這種影響需要被避免。所以稱為精靈程序還需要對其檔案描述符制空。
dup2
驗證函式如下:

#include <fcntl.h>
using namespace std;
int main(int argc,char *argv[]){
        //用於存放轉換成字串形式的時間格式的快取區
        char timeBuf[128] = {0};
        //指定時間
        time_t nowTime = time(NULL);
        strftime (timeBuf,sizeof(timeBuf),"%Y-%m-%d %H-%M-%S",localtime(&nowTime));
        cout << timeBuf << endl;
        getchar();
        pid_t pid = fork
(); if(pid) exit(0); setsid(); /* int fd = open("/dev/null",O_RDWR,0); if(fd != -1){ dup2(fd,STDIN_FILENO); dup2(fd,STDOUT_FILENO); dup2(fd,STDERR_FILENO); if(fd > STDERR_FILENO) close(fd); } * */
sleep(30); cout << "精靈程序a.out" << endl; sleep(60); }

結論描述:
啟動程序,觀察a.out在程序樹的位置,是終端的一個子程序,如下
啟動程序時的pstree
敲擊回車之後,執行了setsid(),手動退出啟動程序的終端,觀察a.out在程序樹的位置,如下
脫離終端之後