linux守護進程daemon
linux守護進程:
linux很多的系統服務都是守護進程,例如本地的系統服務crond計劃任務 , 網絡服務:web httpd
如何將一個進程轉換爲守護進程呢?
一.概念:
進程:
每一個進程都有父進程(祖先進程是INIT進程 ,PID 1)相關係統調用 fork();
子進程終止,父進程會得到通知,並且獲取子進程的退出狀態:相關:wait()
進程組:
每個進程也屬於一個進程組;
每個進程組也有一個ID,ID是組長的PID;
一個進程只能爲自己和子進程設置進程ID;
會話期(session):
會話期是一個或者多個進程組的集合;
setsid()可以建立一個會話期
如果setsid不是進程組的組長的話,會創建一個新的會話期.
1.此進程編程新的會話期的首進程組
2.此進程編程新的進程組的組長
3.脫離控制終端的關係
如果是子進程的組長的話,返回錯誤
爲了保證這一點,所以我們先調用fork 然後再調用 exit
代碼:
pid_t pid,sid;
pid = fork();
if(pid < 0)
{
exit(-1);//error
}
else if(pid > 0)
{
exit(0);//father exit(0)
}
else
{
sid = setsid();//child create
}
......
二.守護進程的特性
1.在後臺運行的;
2.與當前的環境隔離開來,關閉文件描述符,控制終端,會話,以及文件掩碼等等
3.啓動方式 /etc/rc.d /etc/init.d/ shell crond(計劃任務)
三.
編程要點:
1. pid = fork();
if(pid > 0)
{
exit(0);
}//關閉父進程
2. 脫離控制終端,登陸會話和進程組
以上都從父進程中繼承來的,必須要擺脫他們,使之不受影響;
setsid();//一個函數搞定
/*關係 一對多
會話-》進程組-》進程*/
***失敗原因:進程本來就是進程組的組長,但是第一步已經避免了
3.關閉打開的文件描述符
系統默認打開的文件描述符 標準輸入,標準輸出,標準錯誤(0,1,2);
close(STDIN_FILENO);標準輸入
close(STDOUT_FILENO);標準輸出
close(STDERR_FILENO);標準錯誤
4.改變當前目錄
進程活動時,當前的工作目錄所在的文件系統是不能卸載的,所以一般改工作目錄到'/' root
chdir("/");
5.重新設置文件掩碼umask
進程從創建的父進程哪裏繼承了文件掩碼,所以需要重設umask(0);
以上基本上就完成了整個守護進程的操作;
代碼實例:
void init_daemon()
{
pid_t pid,sid;
pid = fork();
if(pid < 0)
{
exit(-1);
}
else if(pid > 0)
{
exit(0);
}
else
{
sid = setsid();
}
chdir("\");
umask(0);
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
}
linux很多的系統服務都是守護進程,例如本地的系統服務crond計劃任務 , 網絡服務:web httpd
如何將一個進程轉換爲守護進程呢?
一.概念:
進程:
每一個進程都有父進程(祖先進程是INIT進程 ,PID 1)相關係統調用 fork();
子進程終止,父進程會得到通知,並且獲取子進程的退出狀態:相關:wait()
進程組:
每個進程也屬於一個進程組;
每個進程組也有一個ID,ID是組長的PID;
一個進程只能爲自己和子進程設置進程ID;
會話期(session):
會話期是一個或者多個進程組的集合;
setsid()可以建立一個會話期
如果setsid不是進程組的組長的話,會創建一個新的會話期.
1.此進程編程新的會話期的首進程組
2.此進程編程新的進程組的組長
3.脫離控制終端的關係
如果是子進程的組長的話,返回錯誤
爲了保證這一點,所以我們先調用fork 然後再調用 exit
代碼:
pid_t pid,sid;
pid = fork();
if(pid < 0)
{
exit(-1);//error
}
else if(pid > 0)
{
exit(0);//father exit(0)
}
else
{
sid = setsid();//child create
}
......
二.守護進程的特性
1.在後臺運行的;
2.與當前的環境隔離開來,關閉文件描述符,控制終端,會話,以及文件掩碼等等
3.啓動方式 /etc/rc.d /etc/init.d/ shell crond(計劃任務)
三.
編程要點:
1. pid = fork();
if(pid > 0)
{
exit(0);
}//關閉父進程
2. 脫離控制終端,登陸會話和進程組
以上都從父進程中繼承來的,必須要擺脫他們,使之不受影響;
setsid();//一個函數搞定
/*關係 一對多
會話-》進程組-》進程*/
***失敗原因:進程本來就是進程組的組長,但是第一步已經避免了
3.關閉打開的文件描述符
系統默認打開的文件描述符 標準輸入,標準輸出,標準錯誤(0,1,2);
close(STDIN_FILENO);標準輸入
close(STDOUT_FILENO);標準輸出
close(STDERR_FILENO);標準錯誤
4.改變當前目錄
進程活動時,當前的工作目錄所在的文件系統是不能卸載的,所以一般改工作目錄到'/' root
chdir("/");
5.重新設置文件掩碼umask
進程從創建的父進程哪裏繼承了文件掩碼,所以需要重設umask(0);
以上基本上就完成了整個守護進程的操作;
代碼實例:
void init_daemon()
{
pid_t pid,sid;
pid = fork();
if(pid < 0)
{
exit(-1);
}
else if(pid > 0)
{
exit(0);
}
else
{
sid = setsid();
}
chdir("\");
umask(0);
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.