1.進程組
1.1 定義
1.進程組是一個或多個進程的
集合
,可接受來自同一終端的信號。
2.每個進程組有唯一的
進程組ID。
3.每個進程有一個組長進程
,組長進程標識是:進程組ID等於進程ID,組長進程可以創建一個進程組.
4.只要在某個進程組中一個進程存在,則該進程組就存在,這與其組長進程是否終止無關。<
a
1.2演示
創建三個後臺進程,sleep 1000 ,sleep 2000,sleep 3000
& :表示將進程放在後臺執行
fg 進程號 //將進城提至前臺
jobs :查看當前有哪些作業
bg 進程號 :喚醒後臺進程
ps axj : a :不僅列出當前用戶的進程,也列出所有其他用戶的進程
x:不僅列出有控制終端的進程,也列出所有無控制終端的進程
j:列出與作業控制相關的信息
2.作業
2.1 定義
shell分前後臺控制的是作業而非進程
一個前臺作業可以由多個進程組成,一個後臺作業也可以有多個進程組成。
作業控制
:shell可以運行一個前臺作業
與多個後臺作業
.
作業與進程組的區別:
如果作業中的某個進程又創建了子進程,則子進程不屬於作業。
當作業運行結束時,shell將自己提到前臺,如果原來的前臺進程還在,自動變爲後臺進程組。
2.2 實例
1 #include <stdio.h>
2 #include <unistd.h>
3
4 int main()
5 {
6 pid_t id=fork();
7 if(id<0)
8 {
9 perror("fork error");
10 return 1;
11 }
12 else if(id==0)
13 {
14 while(1)
15 {
16 printf("child(%d)# I am running!\n",getpid());
17 sleep(1);
18
19 }
20
21 }
23 else //父進程
24 {
25 int i=4;
26 while(i)
27 {
28 printf("parent(%d) #I am going to dead...%d\n",getpid(),i--);
29 sleep(1);
30 }
31 }
32
33 return 0;
運行結果:
運行代碼發現,在父進程運行完畢後,子進程還在運行,輸入ls等命令可以執行,說明此時shell被提到了前臺,即子進程自動變爲後臺進程
3.會話
3.1 定義
會話是一個或多個進程組的集合。一個會話可以有一個
控制終端
。
控制進程
:建立與控制終端相連接的會話首進程
。
一個會話中包括控制進程(會話首進程),一個前臺進程組和任意後臺進程組。
3.2實例
在結果中可以看到,三個進程屬於同一進程組,同一會話,具有同一父進程7985 ,通過命令查看。7985爲 -bash
4.守護進程
4.1定義
1.守護進程又稱爲精靈進程(daemon),是運行在後臺的一種
特殊進程
。
2.它獨立於控制終端並且週期性的執行某種任務或等待處理某些發生的事件
。
3.linux大多服務器由守護進程實現:ssh、web、httpd等
系統服務進程(守護進程)不受用戶登錄註銷的影響,一直運行,無控制終端,不能和用戶直接交互
。
4.2 實例
通過ps zxj | more 查看系統中的進程
a.TPGID爲-1的是無控制終端的進程,即守護進程
b.在COMMAND 用[]括起來的是內核線程,即在內核中創建,無用戶空間代碼,因此沒有程序文件名和命令行,通常用k開頭的名字。
守護進程通常以d結尾的名字,daemon
4.3 創建守護進程
調用setsid函數創建一個新的會話,併成爲會話首進程
#include <unistd.h>
pid_t setsid(void);
//成功返回創建的會話id,出錯返回-1.
注意:調用該函數前,當前進程不允許是進程組的組長,否則返回-1.。即先fork在調用setsid。總結爲
守護進程自成進程組,自成會話
。
如果當前進程原本有一個控制終端,則它將失去這個控制終端,成爲一個無控制終端的進程,即原來的控制終端仍然是打開的,可以讀寫,但只是一個普通而文件而非控制終端.
編寫過程:a.調用umask將文件模式創建屏蔽字設置爲0
b.調用fork,父進程退出(exit)
c.調用setsid創建新回話
d.忽略SIGCHLD信號
e.將當前目錄更改到根目錄
f.關閉不需要的文件描述符或重定向到/dev/null
void mydaemon()
{
umask(0);
pid_t id = fork();
if(id > 0 )
{
exit(1);
}
printf("Debug\n");
setsid(); //創建新會話
chdir("/"); //將工作目錄設置爲根目錄
close(0); //關閉文件描述符
close(1);
close(2);
signal(SIGCHLD,SIG_IGN);//忽略SIGCHLD信號
}
int main()
{
mydaemon();
while(1); //死循環,方便我們查看
return 0;
}
結果爲:
也可使用庫函數
#include <unistd.h>
int daemon(int nochdir, int noclose);
第一個參數nochdir如果設置爲0的話表示將工作目錄改爲根目錄。第二個參數noclose如果設置爲0的話就將文件描述符重定向到/dev/null文件。與上面原理相似。
#include<stdio.h>
#include<unistd.h>
int main()
{
daemon(0,0);
while(1);//死循環爲了方便查看
return 0;
}