第二講 進程核心跟蹤進程的下列資訊啟動並執行位置訪問的檔案信用狀(安全機制)目前的目錄訪問的記憶體空間1.進程的屬性pid 基本屬性pid(進程標識符)和ppid pid_t getpid() // 獲得本進程的進程id pid_t getppid() // 在子進程中執行它,獲得父進程的進程id 舉例 #include <stdio.h>#include <sys/types.h> int main(int argc, char*argv[]){ pid_t id = getpid(); printf("this id num %d/n",id); return 0;}[root@localhost ch01]# gcc –o getpid getpid.c[root@localhost ch01]# ./getpidThis id num 1991 信用狀(安全機制) etc/passwd、etc/group int setgroups(size_t num, const gid_t *list) int getgroups(size_t num, gid_t *lsit) setuid/setgid和系統守護進程 什麼是守護進程 real uid、saved uid、effective uid int setreuid(uid_t ruid, uid_t euid) // BSD提出 int setuid(uid_t euid) // Posix標準uid和gid總結 出錯返回-1,正確執行時返回0在大部分函數原形在unistd.h中定義int setreuid(uid_t ruid,uid_t euid) // 設定當前進程的真實使用者標示符為ruid,以及進程的有效// 使用者標示符為euidint setrgid(gid_t rgid, gid_t egid) // 設定當前進程的真實組標示符為ruid,以及進程的有效組//標示符為euid int setuid(uid_t uid) // 如果是普通使用者調用,則將進程的有效使用者標示符設定為uid // 如果是root使用者調用,則將真實、有效和已儲存的使用者標示符設定為uiditn setgid(gid_t gid) // 如果是普通使用者調用,則將進程的有效使用者組標示符設定為uid // 如果是root使用者調用,則將真實、有效和已儲存的使用者組標示符設定為uidint seteuid(uid_t gid) 等價於setreuid(-1,euid)int setegid(gid_t gid) 等價於setrgid(-1,egid)int setgroups(size_t num, const gid_t *list) // 把當前進程的補充組設為list 函數原型在grp.h中uid_t getuid() // 返回進程的真實使用者標示符uid_t geteuid() // 返回進程的有效使用者標示符gid_t getgid() // 返回進程的真實組標示符gid_t getegid() // 返回進程的有效組標示符size_t getgroups(size_t size, gid_t list[]) // 將當前進程的補充組返回到list中函數原形在grp.h中2.進程相關資訊程式參數int main(int argc ,char *argv[])extern char *environ[] // 全域變數,指向環境變數中的每個元素。聲明在<usrstd.h>中const char *getenv(const char *name) // 如果這個值存在,返回指向全域變數中名字為// name值的指標,否則返回NULLint putenv(const char *string) // Posix標準定義,具有比較好的移植性int setenv(const char *name, const char *value, int overwrite) // BSD定義 例:putenv(“PATH=/bin:/usr/bin”) setenv(“PATH”,”/bin:/usr/bin”,1)資源使用 int getruseage(int who ,strcut rusage *usage) who–RUSAGE_SELF RUSAGE_CHILDREN RUSAGE_BOTH #include <sys/resource.h> struct rusage{ struct timeval ru_utime; // 執行使用者代碼所用的時間,包括運行使用者代碼指定的所有//時間,不包括核心用來完成應用程式請求的 struct timeval ru_stime; //核心用於系統請求的全部時間,其中不包括在系統調用時//進程阻塞所花的時間 long int ru_minflt; // 進程所造成的次要缺陷數 long int ru_majflt; // 進程照成的主要缺陷數 long int ru_nswap; // 進程的訪問而從磁碟調用記憶體的頁面數 ……......}建立使用限制 int getrlimit(int resource ,struct rlimit *rlim) int setrlimit(int resource,const struct rlimit *rlim) struct rlimit{ long int rlim_cur; // 軟式節流值是多少 long int rlim_max; // 應限制是多少}RLIMIT_AS // 進程處於記憶體的最大數量RLIMIT_CORE // 由核心產生的core檔案的最大大小RLIMIT_CPU // 全部cpu時間RLIMIT_DATA // 資料存放區的最大容量RLIMIT_FSIZE // 開啟檔案的最大數目RLIMIT_MEMLOCK RLIMIT_NOFILE // 開啟檔案的最大數RLIMIT_NPROC // 進程可以產生的最大子進程數目RLIMIT_RSS // 可以隨時使用的記憶體容量RLIMIT_STACK // 堆棧儲存區的最大容量3.進程基本元素建立子進程 #include <unistd.h> pid_t fork(); 特別之處:返回兩次 舉例 #include <sys/types.h>#include <stdio.h>#include <unistd.h> int main(void){ pid_t child;if (!(child=fork())) { printf("/nin child/n"); _exit(0); } printf("in parent -- child is %d/n",child); return 0;}[root@localhost ch01]# gcc –o forkd forkd.c[root@localhost ch01]# ./forkd in childin parent – child is 1918等待子進程結束 pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage);WIFEXITED(status) //是否正常退出 WEXITSTATUS(status) //返回進程的結束代碼WISIGNALED(status) //是否被訊號終止 WTERMSIG(status) // 終止進程的訊號的號碼 WIFSTOPPED(status)//進程已被訊號終止 WSTOPSIG(status) //返回停止進程的訊號 pid_t wait(int *status) pid_t waitpid(pid_t pid, int *status, int options) pid_t wait3(int *status, int options ,strcut rusage rusage)運行新進程 int execl(const char *path, const char *arg0,….); int execlp(const char *file, const char *arg0,…); int execle(const char *path, const char *arg0,…); int execv(const char *path, const char **argv); int execvp(const char *file, const char **argv); int execve(const char *file, const char **argv); 運行成功沒有返回;失敗返回-1 execl(“/bin/cat”,”/bin/cat”,”/etc/passwd”, ”/etc/group”, NULL); char * argv[] = {“./cat”, ”/etc/passwd”, “/etc/group”, NULL}; execv(“/bin/cat”, argv); char *newenv[] = {“PATH = /bin:/usr/bin”,”HOME=/home/sweethome”,NULL} execle(“/usr/bin/env”, ”/usr/bin/env”, NULL, newenv); char *argv[]={“/usr/bin/env”, NULL}; char *newenv[]={“PATH=/bin:usr/bin”, ”HOME=/home/sweethome”, NULL} execve(“/usr/bin/env”, argv, newenv); execlp(“cat”, “cat”, “/etc/passwd”, “/etc/group”, NULL); char *argv[]={“./cat”, “/etc/passwd”, “/etc/group”, NULL}; execvp(“cat”, argv);終止 void exit(int exitcode); void _exit(int exitcode); int kill(pid_t pid, int signum);4.簡單子進程system() int system(const char *cmd) // 首先fork一個exec系列的函數,在這個中運行了一個shell的子程式,然後用這個shell運行cmd命令。原來的程式等待子進程退出,然後返回類似於wait函數的返回。 /bin/sh 樣本#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/wait.h> int main(){ int result; result = system("exec ls -l"); if (!WIFEXITED(result)){ printf("abnormal exit/n"); } return 0;}[root@localhost ch01]# gcc –o testsystem testsystem.c[root@localhost ch01]# ./testsystem總用量 304-rwx------ 1 root root 11791 5月 16 22:10 a.out-rwx------ 1 root root 162 5月 21 21:50 ~$ch02.doc-rwx------ 1 root root 95232 5月 21 21:57 ch02.doc-rwx------ 1 root root 11791 5月 16 22:11 forkd-rwx------ 1 root root 218 5月 16 22:09 forkd.c-rwx------ 1 root root 11649 5月 10 20:32 getpid-rwx------ 1 root root 144 5月 10 20:32 getpid.c-rwx------ 1 root root 11693 5月 21 22:05 testsystem-rwx------ 1 root root 211 5月 21 22:05 testsystem.c-rwx------ 1 root root 0 5月 21 22:06 test.tmp-rwx------ 1 root root 94720 5月 16 22:45 ~WRL0001.tmp-rwx------ 1 root root 94208 5月 21 21:50 ~WRL0003.tmp-rwx------ 1 root root 94208 5月 21 21:52 ~WRL0005.tmp-rwx------ 1 root root 95232 5月 21 21:56 ~WRL2785.tmp-rwx------ 1 root root 94208 5月 21 21:52 ~WRL4030.tmp從進程讀或寫FILE *popen(const char *cmd, const char *mode)int pclose(FILE *stream);5.會話和進程組會話控制終端進程組孤兒進程組