linux 系統編程 進程
進程
進程號一般不重復使用
空閑進程 pid 0 ,內核運行的第一個進程 init pid 1.
內核搜索init的順序,如果找不到,內核就會發出panic掛起
/sbin/init
/etc/init
/bin/etc
/bin/sh
進程號最大值32768 老unix用16位計算pid,可以在/proc/kernel/pid_max的值修改
#include<sys/types.h>
#include<unistd.h>
Pid_t getpid(); //返回調用進程的pid
Pid_t getppid(); //返回調用進程的父進程pid
1. Exec
#include<unistd.h>
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 execve(const char *path, char *const argv[], char *const envp[]);
Path 指向要調用文件的映像,如路徑,arg為第一個參數,一般為文件名,後面接可變參數,最後以NULL結尾。
執行完替換之後,原進程所有數據丟失,原進程設置的信號處理函數和掛起的信號丟失,原進程對線程的設置丟失,進程的統計信息丟失。但進程pid等不變。
詳細解釋:http://blog.csdn.net/lianghe_work/article/details/47704105
2. fork()
#include<sys/types.h>
#include<ubistd.h>
Pid_t fork();
生成一個和父進程幾乎一模一樣的進程
不同點:
Pid和ppid
子進程資源統計信息會清零
掛起信號和文件鎖不會繼承
3. exit
#include<stdlib.h>
Void exit(int status);
Status 標示退出狀態 status & 0377會返回給父進程確認
EXIT_SUCCESS 0 EXIT_FAILURE 非零
關閉流程:
在系統中註冊的逆序調用atexit或onexit
清空所有已經打開的標準I/O
刪除由tmpfile()創建的所有臨時文件
調用_exit讓內核處理終止進程剩余工作
內核清理:申請的內存,打開的文件,system V信號
進程可以直接調用_exit,但這樣一些進程處理的清理未完成,不合理。只有vfork一定要調用_exit。
其他方式結束進程:
Main函數返回或者調用exit(0)。
SIGTERM 和 SIGKILL被觸發
程序段錯誤或者內存耗盡內核強制殺死
4. atexit
#include<stdlib.h>
Int atexit(void (*function) (void));
函數成功返回會將函數註冊到進程正常結束的時候調用。
如果進程調用了exec,那麽atexit不會被調用,進程被信號結束也不會調用這個函數,被註冊的函數應該是無參無返回的,調用順序和註冊順序相反。
進程結束時,內核會給父進程發送信號SIGCHILD,一般這個信號會被忽略。如果有需要可以使用signal或者sigaction處理
等待死亡的進程會保留一定的信息等待父進程查看,父進程查看後子進程消亡,如果不查看就會成為僵屍進程
5.wait
#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int *status);
返回已經終止的子進程 status子進程結束的狀態
如果沒有子進程結束會阻塞
6.waitpid
#include<sys/types.h>
#include<sys/wait.h>
Pid_t waitpid(pid_t pid,int *status,int options);
Pid 取值
-1 pid絕對值的進程組的所有子進程
0 同一進程組的任意進程
>0 指定的子進程的等待
Options取值:
WNOHANG 不阻塞
實際用戶ID 真實的用戶ID,無法修改,會在各個地方被繼承root可以修改他
有效用戶ID 進程使用的用戶ID,權限驗證使用這個ID,使用setuid可以修改
保存設置的用戶ID
文件系統用戶ID
#include<sys/types.h>
#include<unistd.h>
Int setuid(uid_t uid); //root用戶可以設置任意值,非root設置為實際ID和保存ID
Int setgid(gid_t gid);
Int seteuid(uid_t euid); //同上
Int setegid(gid_t egid);
Int setreuid(uid_t ruid,uid_t euid);
Int setregid(gid_t rgid,gid_t egid);
守護進程:
- fork()創建新的進程,
- 在守護進程父進程中調用exit
- 調用setsid 使得進程有新的進程組和新的會話
- 使用chdir將當前的工作目錄改為根目錄
- 關閉所有的文件描述符
- 打開0,1,2文件描述符,重定向到/dev/null。
線程:
每個線程都有獨占的一個虛擬處理器,獨自的寄存器組,指令計數器和處理器狀態。
同一進程中的線程共享同一的地址空間(動態內存,映射文件,目標代碼等等),打開的文件和其他內核資源。
讓出處理器的系統調用
7.Sched_yield();
#include<sched.h>
Int sched_yield();
中斷進程,內核會運行新的進程,但是如果沒有其他進程就緒,進程會立馬恢復,所以一般這個調用沒有太大意義。
進程優先級是值越小,優先級越高,開始運行越快,執行時間越長
8.nice
#include<unistd.h>
Int nic(int inc);
成功在現在的優先級上加inc返回新的優先級。只有擁有CAP_SYS_NICE(root)的才能使用負值
由於優先級可以返回負值,所有返回成功失敗需要errno測試,在使用前將errno清零
10.getpriority ,setpriority
#include<sys/time.h>
#include<sys/resource.h>
Int getpriority(int which,int who) ;
Int setpriority (int which,int who,int prio) ;
Which 取值:
PRIO_PROCESS PRIO_PGRP PRIO_USER
對應的who
進程id,進程組ID,用戶id
只有擁有CAP_SYS_NICE(root)的進程才可以降低nice的值,提高優先級
11.ioprio_get ioprio_set
Int ioprio_get(int which,int who);
Int ioprio_set(int which,int who,int prio);
12 .Getlimit setlimit
#include<sys/time.h>
#include<sys/resource.h>
Struct rlimit{
Rlimit_t rlim_cur; //軟限制 內核執行的限制
Rlimit_t rlimit_max;//硬限制
}
Int Getlimit(int resource ,struct rlimit *rlim);
Int setlimit(int resource ,const struct rlimit *rlim);
Resource RLIMIT_CUP
不具備CAP_SYS_NICE(root)的進程只能調低硬限制
RLIMIT_FSIZE
RLIMIT_CORE
RLIM_INFINITY
名稱 |
意義 |
RLIMIT_AS |
進程總共可用的內存大小的最大值 |
RLIMIT_CORE |
core文件的最大尺寸,如果為0說明不能創建core文件 |
RLIMIT_CPU |
CPU時間的最大值(單位:秒) |
RLIMIT_DATA |
數據段大小的最大值 |
RLIMIT_FSIZE |
創建文件的大小的最大值 |
RLIMIT_LOCKS |
進程可建立的文件鎖的數量的最大值 |
RLIMIT_MEMLOCK |
進程中使用mlock鎖定內存的最大尺寸 |
RLIMIT_NOFILE |
進程中文件的打開數量的最大值 |
RLIMIT_NPROC |
每個real user id的子進程數量的最大值 |
RLIMIT_RSS |
最大常駐存儲區大小 |
RLIMIT_SBSIZE |
socket緩沖的大小的最大值 |
RLIMIT_STACK |
棧的最大尺寸 |
RLIMIT_VMEM |
=RLIMIT_AS |
linux 系統編程 進程