08.進程控制

1.進程標識

  • 進程ID是唯一的,但也是可複用的,大部分系統採用延遲複用算法
  • ID爲0的通常是調度進程,常被稱爲交換進程,是內核的一部分,不執行磁盤上的程序(所以也叫系統進程)
  • 進程ID爲1的通常是init進程,自舉過程由內核調用,超級用戶特權運行,但是普通的用戶進程,不會終止
#include <sys/types.h>
#include <unistd.h>

pid_t getpid(void);
pid_t getppid(void);
uid_t getuid(void);
uid_t geteuid(void);
gid_t getgid(void);
gid_t getegid(void);

2、fork()函數

#include <unistd.h>
pid_t fork(void);
  • 子進程返回0
  • 父進程返回子進程的進程ID
  • fork之後經常跟exec,所以採用了寫時複製技術
  • 文件共享:
    • 打開的文件描述符的複製類似於執行了dup()
    • 父子進程共享同一文件偏移量
  • 父子進程的區別:
    • 子進程不繼承文件鎖
    • 子進程未處理的鬧鐘被清除
    • 子進程的未處理信號集設置爲空集

3、vfork()

#include <sys/types.h>
#include <unistd.h>
pid_t vfork(void);

可移植的程序不應該使用這個函數

  • vfork()創建的子進程並不會完全複製父進程的地址空間,因爲會馬山調用exec
  • 子進程在調用exec()前在父進程空間中運行
  • vfork保證子進程先運行,子進程調用exec或exit後父進程才恢復運行

4、exit()

  • 進程有5中正常終止的方法:

    • main()中return
    • exit()
    • _[eE]xit
    • 最後一個線程執行return
    • 最後一個線程調用pthread_exit()
  • 進程的3中異常終止狀態

    • 調用abort()
    • 接收到某些信號
    • 最後一個線程對"取消"作出響應
  • 父進程在子進程前終止,子進程編程殭屍進程

  • 子進程在父進程前終止,內核爲子進程保存一定量的信息(包括進程ID,終止狀態,CPU使用時間等)


5、wait()和waitpid()

#include <sys/types.h>
#include <sys/wait.h>

pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
  • 進程終止時向父進程發送SIGCHLD信號
  • 調用wait時:
    • 子進程還活着則阻塞
    • 以終止則立即返回
    • 沒有任何子進程則出錯返回
  • 返回值指示退出狀態、信號編號、是否產生core文件等
    WIFEXITED(status)
    WEXITSTATUS(status)
    WIFSIGNALED(status)
    WTERMSIG(status)
    WCOREDUMP(status)
    WIFSTOPPED(status)
    WSTOPSIG(status)
    WIFCONTINUED(status)
    

6、waitid()

int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
  • idtype
    • P_PID:等待特定進程
    • P_PGID:等待特定進程組中的任一子進程
    • P_ALL:等待任一子進程
  • options
    • WCONTINUED:等待一個進程,它以前曾被停止,此後又繼續,但狀態尚未報告
    • WEXITED:等待已退出的進程
    • WNOHANG:非阻塞
    • WNOWAIT:不破壞子進程的退出狀態
    • WSTOPPED:進程已經停止,但狀態尚未報告

7、wait3()和wait4()

#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/wait.h>

pid_t wait3(int *status, int options,
            struct rusage *rusage);
pid_t wait4(pid_t pid, int *status, int options,
            struct rusage *rusage);
  • 允許內核返回由終止進程及其所有子進程使用的資源概況

8、競爭條件

多個進程企圖對共享數據進行處理,結果取決於進程運行順序

  • 爲了避免競爭條件和輪詢,進程間需要某種形式信號的發送和接收方法

9、exec()函數

#include <unistd.h>
extern char **environ;
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg,
            ..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],
            char *const envp[]);
  • 進程調用exec函數時,進程執行的程序完全替換爲新進程
  • 進程ID不變,因爲只是用磁盤上的新程序替換了當前進程的正文段、數據段、堆棧
  • …(暫時用不到就不看了)

10、更改用戶ID和更改組ID

int setuid(uid_t uid);
int setgid(gid_t gid);
  • 在linux中,特權以及訪問控制是基於用戶ID和組ID的
  • 更改用戶ID規則
    • 若進程有root權限,實際/有效/保存的設置用戶ID設置爲uid
    • 。。。

11、解釋器文件

  • 起始行是:
    #! pathname [optional-argument]
    

12、system()函數

int system(const char *command);
  • command爲空時,可用時返回非0值
  • 返回值
    • -1:fork失敗或waitpid返回EINTR之外的值
    • 127?:exec失敗
    • shell的終止狀態:成功

13、進程會計

啓動進程會計後,每當進程結束內核就寫一個會計記錄:包括命令名、CPU時間總量、用戶ID、組ID、啓動時間內等

int acct(const char *filename);
  • 該函數用以啓用和禁用進程會計,但至今沒有一個標準做了聲明,只有accton命令用了這個函數

14、用戶標識

任一進程都可以得到實際用戶ID和有效用戶ID及組ID

#include <unistd.h>
char *getlogin(void);
int getlogin_r(char *buf, size_t bufsize);
#include <stdio.h>
char *cuserid(char *string);
  • 用以獲取登錄名

15、進程調度


16、進程時間

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章