會話
創建會話
創建一個會話需要注意以下6點注意事項
- 調用進程不能是進程組組長,該進程變成新會話首進程
- 該進程成為一個新進程組的組長進程
- 需要root權限(nbuntu不需要)
- 新會話丟棄原有的控制終端,該會話沒有控制終端
- 該調用進程是組長進程,則出錯返回
- 建立新會話時,先調用fork,父進程終止,子進程調用setsid
getsid 函數
獲取進程所屬的會話ID
pid_t getsid(pid_t pid);
成功:返回調用進程的會話 ID;失敗:-1,設置 errno
pid 為 0 表示察看當前進程 session ID
ps ajx 命令查看系統中的進程。
- 參數 a 表示不僅列當前用戶的進程,也列出所有其他用戶的進程,
- 參數 x 表示 不僅列有控制終端的進程,也列出所有無控制終端的進程,
- 參數 j 表示列出與作業控制相關的信息。
組長進程不能成為新會話首進程,新會話首進程必定會成為組長進程。
setsid 函數
創建一個會話,并以自己的 ID 設置進程組 ID,同時也是新會話的 ID。
pid_t setsid(void);
成功:返回調用進程的會話 ID;失敗:-1,設置 errno
調用了 setsid 函數的進程,既是新的會長,也是新的組長。
練習: fork 一個子進程,并使其創建一個新會話。查看進程組 ID、會話 ID 前后變化
#include<stdlib.h>
#include<unistd.h>int main(void)
{pid_t pid;if((pid = fork()< 0)){perror("fork");exit(1);}else if(pid == 0){ printf("child process PID is %d\n",getpid());printf("Group ID of child is %d\n",getpgid(0));printf("Session ID of child is %d\n",getsid(0));sleep(10);setsid(); //子進程非組長進程,故其成為新會話首進程,且成為組長進程。該進
程id即為會話進程printf("Changed:\n");printf("child process PID is %d\n",getpid());printf("Group ID of child is %d\n",getpgid(0));printf("Session ID of child is %d\n",getsid(0));sleep(20);exit(0); } return 0;
}
結果:
守護進程
- Daemon(精靈)進程,是 Linux 中的后臺服務進程,通常獨立于控制終端并且周期性地執行某種任務或等待處理 某些發生的事件。一般采用以 d 結尾的名字。
- Linux 后臺的一些系統服務進程,沒有控制終端,不能直接和用戶交互。不受用戶登錄、注銷的影響,一直在運行著,他們都是守護進程。如:預讀入緩輸出機制的實現;ftp 服務器;nfs 服務器等。
- 創建守護進程,最關鍵的一步是調用 setsid 函數創建一個新的 Session,并成為 SessionLeader。
創建守護進程
-
創建子進程,父進程退出
所有工作在子進程中進行形式上脫離了控制終端 -
在子進程中創建新會話
setsid()函數
使子進程完全獨立出來,脫離控制 -
改變當前目錄為根目錄
chdir()函數
防止占用可卸載的文件系統
也可以換成其它路徑 -
重設(指定)文件權限掩碼
umask()函數
防止繼承的文件創建屏蔽字拒絕某些權限
增加守護進程靈活性 -
將0/1/2重定向/dev/null dup2()關閉文件描述符
繼承的打開文件不會用到,浪費系統資源,無法卸載 -
開始執行守護進程核心工作
-
守護進程退出處理程序模型
#include<stdio.h>#include<unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h> void mydaemond(void){pid_t pid,sid;int ret;pid = fork();if(pid > 0){ //父進程退出return 0;} //創建會話sid = setsid();ret = chdir("/home/itcast/"); if( ret == -1 ){perror("chdir error");exit(1);} umask(0022);close(STDOUT_FILENO);open("/dev/null",O_RDWR);dup2(0,STDOUT_FILENO);dup2(0,STDERR_FILENO);}int main(void){mydaemond();while(1){}return 0;}