首頁 > 軟體

Linux 的行程群組、對談、守護行程

2020-06-16 18:03:07

一、行程群組ID

每個進程都屬於一個行程群組。每個行程群組有一個領頭進程。行程群組是一個或多個進程的集合,通常它們與一組作業相關聯,可以接受來自同一終端的各種信號。每個行程群組都有唯一的行程群組ID(整數,也可以存放在pid_t型別中)。行程群組由行程群組ID來唯一標識。除了進程號外(PID)之外,行程群組ID也是一個進程的必備屬性之一。

getpgrp: 獲得行程群組 id, 即領頭進程的 pid
#include <unistd.h>
pid_t getpgrp(void);
//返回值;呼叫進程的行程群組ID

#include<unistd.h>
pid_t getpgid(pid_t pid);
//若成功返回行程群組id,失敗則返回-1.

每個行程群組都有一個組長進程,組長進程的進程號等於行程群組ID。組長進程可以建立一個行程群組、建立該組中的進程。只要某個行程群組中有一個進程存在,則該行程群組就存在,與組長進程是否終止無關。從行程群組建立開始到其中最後一個進程離開為止的時間區間成為行程群組的生存期。行程群組中最後一個進程可以終止或者轉移到另一個行程群組中。
顯示子進程和父進程的組id

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    pid_t pid;

    if ((pid=fork())<0) {
        printf("fork error!");
    }else if (pid==0) {
        printf("The child process PID is %d.n",getpid());
        printf("The Group ID is %d.n",getpgrp());
        printf("The Group ID is %d.n",getpgid(0));
        printf("The Group ID is %d.n",getpgid(getpid()));
        exit(0);
    }

    sleep(3);
    printf("The parent process PID is %d.n",getpid());
    printf("The Group ID is %d.n",getpgrp());

    return 0;
}

程式執行的結果:

二、對談
對談是一個或多個行程群組的集合。例如:


#include<unistd.h>
pid_t setsid(void);
如果呼叫此函數的進程不是一個行程群組的組長,則此函數就會建立一個新的對談,結果發生三件事:
1、該進程變成新對談的首進程。此時,該進程是新對談中唯一的進程。
2、該進程成為一個行程群組的組長進程。新的行程群組ID就是呼叫進程的ID。
3、該進程沒有控制終端。如果在呼叫setsid之前該進程有一個控制終端,那麼這種聯絡也會斷掉。
如果該進程已經是一個行程群組的組長,則此函數返回錯誤。為了保證不會發生這種事情,通常先呼叫fork,然後使其父進程終止,而子進程則繼續。因為子進程繼承了父進程的組ID,而其ID是新分配,兩者不可能相等,所以就保證了子進程不會是一個行程群組長。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    pid_t pid;

    if ((pid=fork())<0) {
        printf("fork error!");
        exit(1);
    }else if (pid==0) {
        printf("The child process PID is %d.n",getpid());
        printf("The Group ID of child is %d.n",getpgid(0));
        printf("The Session ID of child is %d.n",getsid(0));
        sleep(10);
        setsid(); // 子進程非組長進程,故其成為新對談首進程,且成為組長進程。該行程群組id即為對談進程
        printf("Changed:n");
        printf("The child process PID is %d.n",getpid());
        printf("The Group ID of child is %d.n",getpgid(0));
        printf("The Session ID of child is %d.n",getsid(0));
        sleep(20);
        exit(0);
    }

程式執行的結果:

三、守護行程
在linux或者unix系統中在系統的引導的時候會開啟很多服務,這些服務就叫做守護行程。為了增加靈活性,root可以選擇系統開啟的模式,這些模式叫做執行級別,每一種執行級別以一定的方式設定系統。 守護行程是脫離於終端並且在後台執行的進程。守護行程脫離於終端是為了避免進程在執行過程中的資訊在任何終端上顯示並且進程也不會被任何終端所產生的終端資訊所打斷。

守護行程程式設計步驟
  1. 建立子進程,父進程退出
    •所有工作在子進程中進行
    •形式上脫離了控制終端
  2. 在子進程中建立新對談
    •setsid()函數
    •使子進程完全獨立出來,脫離控制
  3. 改變當前目錄為根目錄
    •chdir()函數
    •防止占用可解除安裝的檔案系統
    •也可以換成其它路徑
  4. 重設檔案許可權掩碼
    •umask()函數
    •防止繼承的檔案建立遮蔽字拒絕某些許可權
    •增加守護行程靈活性
  5. 關閉檔案描述符
    •繼承的開啟檔案不會用到,浪費系統資源,無法解除安裝
    •getdtablesize()
    •返回所在進程的檔案描述符表的項數,即該進程開啟的檔案數目

該範例首先建立了一個守護行程,然後讓該守護行程每個10s在/tmp/dameon.log中寫入一句話。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/wait.h>
       
#define MAXFILE 65535
int main()
{
 pid_t pc;
 int i,fd,len;
 char *buf="This is a Dameonn";
 len =strlen(buf);
 pc=fork();
 if(pc<0){
  printf("error forkn");
  exit(1);
 }else if(pc>0)
 exit(0);
 setsid();
 chdir("/");
 umask(0);
 for(i=0;i<MAXFILE;i++)
  close(i);
 while(1){
  if((fd=open("/tmp/dameon.log",O_CREAT|O_WRONLY|O_APPEND,0600))<0){
   perror("open");
   exit(1);
   }
  write(fd, buf, len+1);
  close(fd);
  sleep(10);
 }
}

我們可以看到程式每個10s就在對應的檔案中寫入內容。

本文永久更新連結地址http://www.linuxidc.com/Linux/2015-04/115764.htm


IT145.com E-mail:sddin#qq.com