日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

进程 、进程组、会话、控制终端之间的关系

發布時間:2023/12/9 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 进程 、进程组、会话、控制终端之间的关系 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一個進程組可以包含多個進程

????? 進程組中的這些進程之間不是孤立的,他們彼此之間或者存在者父子、兄弟關系,或者在功能有相近的聯系。

????? 那linux為什么要有進程組呢?其實提供進程組就是方便管理這些進程。假設要完成一個任務,需要同時并發100個進程,當用戶由于

???? 某種原因要終止這個任務時,要是沒有進程組,就需要一個個去殺死這些進程,設置了進程組之后,就可以對進程組中的每個進程進行殺死。??

???? 每個進程必定屬于一個進程組,也只能屬于一個進程組。??

??? 一個進程除了有進程ID外,還有一個進程組ID,每個進程組也有唯一的進程組ID。

?? 每個進程組有一個進程組組長,進程組組長的進程ID和組ID相同


函數getpgrp和getpgid可以返回調用進程的進程組ID

??? #include <unistd.h>

?? pid_t getpgrp(void);

? pid_t? getpgid(pid_t pid);

??????????? //返回值:成功則返回進程組ID,失敗返回-1.

函數setpgid可以使進程加入現有的組或者創建一個新進程組。

?? #include <unistd.h>

? int setpgid(pid_t pid, pid_t pgid );

setpgid將pid進程的進程組ID設置為pgid.

(1)pid=pgid ,則表示將pid指定的進程設為進程組組長

(2)pid=0 .則使用調用進程的進程ID

(3)pgid=0,則將pid指定進程用作進程組ID。

????????

?

一個會話又可以包含多個進程組。一個會話對應一個控制終端

??

??? linux是一個多用戶多任務的分時操作系統,必須要支持多個用戶同時登陸同一個操作系統,當一個用戶登陸一次終端時就會產生一個會話,

? 每個會話有一個會話首進程,即創建會話的進程,建立與終端連接的就是這個會話首進程,也被稱為控制進程。一個會話可以包括多個進程組,

?? 這些進程組可被分為一個前臺進程組和一個或多個后臺進程組。為什么要這么分呢?前臺進程組是指需要與終端進行交互的進程組(只能有一個)

? 比如有些進程是需要完成IO操作的,那么這個進程就會被設置為前臺進程組.當我們鍵入終端的中斷鍵和退出鍵時,就會將信號發送到前臺進程

? 組中的所有進程。而 后臺進程組是指不需要與終端進程交互的進程組,比如:一些進程不需要完成IO 操作,或者一些守護進程就會 被設置為后臺進程組(可以有多個),

? (這是我的理解,不知道對錯)。? 如果終端接口檢測到網絡已經斷開連接,則會將掛斷信號發送給會話首進程。

????????????

進程調用setsid函數建立一個新會話.

#include <unistd.h

#include <unistd.h>

pid_t? setsid(pid_t pid);

? ? ? ? ? //返回:成功則返回進程組ID,失敗則返回-1.

如果調用次函數的進程不是進程組的組長,則會創建一個新會話,結果將發生下面3件事情:

(1)該進程會變為新會話的首進程。

(2)該進程會成為一個新進程組的組長進程

(3)該進程沒有控制終端。

如果該調用進程已經是一個進程組的組長,則調用會出錯。

為了保證不會出錯,通常先fork一個子進程,在關閉父進程,因為子進程繼承了父進程的進程組ID,

而進程iD則是新分配的,兩者不可能相等,從而保證了子進程不會是進程組組長。(后面編寫守護進程時會用到。)

怎樣編寫守護進程:

1. 在后臺運行。?
為避免掛起控制終端將Daemon放入后臺執行。方法是在進程中調用fork使父進程終止,讓Daemon在子進程中后臺執行。?
if(pid=fork())?
exit(0);//是父進程,結束父進程,子進程繼續?
2. 脫離控制終端,登錄會話和進程組?
有必要先介紹一下Linux中的進程與控制終端,登錄會話和進程組之間的關系:進程屬于一個進程組,進程組號(GID)就是進程組長的進程號(PID)。登錄會話可以包含多個進程組。這些進程組共享一個控制終端。這個控制終端通常是創建進程的登錄終端。?
控制終端,登錄會話和進程組通常是從父進程繼承下來的。我們的目的就是要擺脫它們,使之不受它們的影響。方法是在第1點的基礎上,調用setsid()使進程成為會話組長:?
setsid();?
說明:當進程是會話組長時setsid()調用失敗。但第一點已經保證進程不是會話組長。setsid()調用成功后,進程成為新的會話組長和新的進程組長,并與原來的登錄會話和進程組脫離。由于會話過程對控制終端的獨占性,進程同時與控制終端脫離。?
3. 禁止進程重新打開控制終端?
現在,進程已經成為無終端的會話組長。但它可以重新申請打開一個控制終端。可以通過使進程不再成為會話組長來禁止進程重新打開控制終端:?

if(pid=fork())?
exit(0);//結束第一子進程,第二子進程繼續(第二子進程不再是會話組長)?
4. 關閉打開的文件描述符?
進程從創建它的父進程那里繼承了打開的文件描述符。如不關閉,將會浪費系統資源,造成進程所在的文件系統無法卸下以及引起無法預料的錯誤。按如下方法關閉它們:?
for(i=0;i 關閉打開的文件描述符close(i);>?
5. 改變當前工作目錄?
進程活動時,其工作目錄所在的文件系統不能卸下。一般需要將工作目錄改變到根目錄。對于需要轉儲核心,寫運行日志的進程將工作目錄改變到特定目錄如/tmpchdir("/")?
6. 重設文件創建掩模?
進程從創建它的父進程那里繼承了文件創建掩模。它可能修改守護進程所創建的文件的存取位。為防止這一點,將文件創建掩模清除:umask(0);?
7. 處理SIGCHLD信號?
處理SIGCHLD信號并不是必須的。但對于某些進程,特別是服務器進程往往在請求到來時生成子進程處理請求。如果父進程不等待子進程結束,子進程將成為僵尸進程(zombie)從而占用系統資源。如果父進程等待子進程結束,將增加父進程的負擔,影響服務器進程的并發性能。在Linux下可以簡單地將SIGCHLD信號的操作設為SIG_IGN。?
signal(SIGCHLD,SIG_IGN);?
這樣,內核在子進程結束時不會產生僵尸進程。這一點與BSD4不同,BSD4下必須顯式等待子進程結束才能釋放僵尸進程。?


daemontest.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
void init_daemon()
{
?? pid_t pid ;
?? int i ;
?? pid =fork();
?? if(pid<0)
?? {
?????? printf("fork error secondly!\n");
?????? exit(1);
?? }
?? else if(pid>0)//結束父進程
?? {
?????? printf("this is first parent process!\n");
?????? exit(0);
?? }//子進程繼續運行
?? setsid() ;//前面為setsid正確調用提供了前提,使子進程成為新的會話組長和
???????? //新的進程組長
?? pid=fork();
?? if(pid<0)//子進程成為無終端的會話組長,但是還是可以打開終端,為了
????????? //使進程脫離終端,使之成為不是會話組長
?? {
?????? printf(" fork error secondly!\n");
?????? exit(1);
?? }
?? else if(pid>0)//關閉第一個子進程
?? {
??????? printf("this is first child process!\n");
??????? exit(0);
?? }//第二個子進程繼續運行
?? for(i=0;i<NOFILE;i++)
?? {
????? close(i);
?? }
?? chdir("/tmp");
?? umask(0);
?? return;
}


main.c

#include <stdio.h>
#include <stdlib.h>
void init_daemon(void);

int main(void)
{
???? FILE *fp ;
???? init_daemon() ;
???? while(1)
???? {
????????? if((fp=fopen("daemon.log","a"))>=0)
?? ?? {
?? ?????? fprintf(fp,"%s","good");
?? ?????? fclose(fp);
?? ?????? sleep(10);
?? ?? }
??? ?
???? }
???? exit(0);
}


運行:

yuan@YUAN:~$ ./daemontest
this is first parent process!
this is first child process!
yuan@YUAN:~$ ps -axj

結果:

? PPID?? PID? PGID?? SID TTY????? TPGID STAT?? UID?? TIME COMMAND


??? 1? 2970? 2969? 2969 ??????????? -1 S???? 1000?? 0:00 ./daemontest

總結

以上是生活随笔為你收集整理的进程 、进程组、会话、控制终端之间的关系的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。