1,ps 查看當前系統的進程信息
PID TTY TIME CMD
2757 pts/0 00:00:00 bash
2881 pts/0 00:00:00 ps
默認顯示與當前終端相關的進程
ps -f//當前詳細信息
ps -e//所有進程
UNIX-----Solari
守護進程,Daemon進程,服務進程。
S休眠狀態
O可運行狀態(就緒)
R運行狀態
T掛起狀體(和休眠狀態基本一樣,休眠是主動的,掛起是被動的)
Z殭屍進程(僵死進程)
Linux:進程的狀態比較多
2,進程間的關係(父子關係)
init(1)
1)父進程啓動子進程後,父子進程同時執行。如果子進程先結束,子進程給父進程發信號,
父進程回收子進程的相關資源
2)父進程啓動子進程後,父子進程同時運行。如果父進程先結束,子進程馬上認init作爲自己的父進程。
init叫linux的孤兒院
3)父進程啓動子進程後,父子進程同時運行。如果子進程先結束,子進程給父進程發信號,
但是父進程沒有及時回收子進程的資源或子進程沒來得及發信號,子進程就成殭屍進程了。
子進程已經結束,父進程的進程表中存在子進程的標誌,所以殭屍進程殺不死
二,進程描述符
進程ID是唯一的,但可以重用。當一個進程終止時,其進程ID就可以再次使用
進程ID非負整數表示
延遲重用
三,
getpid()//獲取進程id
getppid()//獲取父id
getuid()//獲取當前用戶的屬主,返回有效身份
geteuid()//獲取當前用戶的屬主,返回的也是有效身份
#include<stdio.h>
#include<unistd.h>
int main(){
printf("pid:%d\n",getpid());
return 0;
}
四,fork() 創建進程
fork是通過複製自己來創建子進程的。全部複製一個子進程,底層通過clone函數
父子進程沒有規定誰先運行,但是在linux有一個機制,子進程先執行
子進程從fork快要結束的時候執行,從fork後面開始執行
fork函數一次調用,返回兩次,父進程返回一次,子進程返回一次。子進程返回0
父進程返回子進程的pid
#include<stdio.h>
#include<unistd.h>
int main(){
printf("程序開始執行\n");
fork();
printf("程序執行結束\n");
return 0;
}
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main(){
printf("程序開始執行\n");
pid_t pid = fork();
printf("pid=%d,程序執行結束\n",pid);
return 0;
}
fork2.c
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
int main(){
printf("程序開始執行\n");
pid_t pid = fork();
if(pid == -1){}
if(pid == 0){//子進程
printf("我是子進程,pid=%d,我的父進程是:%d\n",getpid(),getppid());
}else{//父進程
printf("我是父進程,pid=%d,我的子進程是:%d\n",getpid(),pid);
}
printf("%d進程結束運行\n",getpid());
return 0;
}
結果:
possible@ubuntu:~/Desktop/test$ gcc fork2.c
possible@ubuntu:~/Desktop/test$ ./a.out
程序開始執行
我是父進程,pid=3836,我的子進程是:3837
3836進程結束運行
possible@ubuntu:~/Desktop/test$ 我是子進程,pid=3837,我的父進程是:1
3837進程結束運行
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
int i1 = 100;
int main(){
int i2 = 10;
pid_t pid = fork();
int i3 = 1000;
char* str = malloc(20);
strcpy(str,"abcdef");
if(pid == -1){
perror("子進程創建失敗");
exit(-1);
}
if(pid == 0){//子進程
i1 = 200;
i2 = 20;
i3 = 2000;
str[0] = 'A';
printf("in child i1=%d\n",i1);
printf("in child i2=%d\n",i2);
printf("in child i3=%d\n",i3);
printf("in child str=%s\n",str);
}else{//父進程
printf("in father i1=%d\n",i1);
printf("in father i2=%d\n",i2);
printf("in father i3=%d\n",i3);
printf("in father str=%s\n",str);
exit(-1);
}
return 0;
}
注:全局區,棧區,堆區,緩衝區都會複製
fork4.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
int main(){
int fd = open("a.txt",O_RDWR|0_CREAT,0666);
if(fd == -1){}
int pid = fork();
if(pid == 0){//子進程
for(char c='A', c<='Z',c++){
write(fd,&c,1);
sleep(1);
}
exit(0);
}
//父進程
char c;
for(c='a'; c<='z'; c++){
write(fd,&c,1);
sleep(1);
}
return 0;
return 0;
}
注:文件表沒有被複制,因爲文件表不是進程的一部分,子進程和父進程指向同一個文件
五,fork失敗的原因
系統中有太多的進程
實際用戶ID的進程總數已經超過系統限制
六,vfork()
和fork()不同的是,沒有複製父進程的東西,而是空的
七,進程終止的情況
main函數執行return,在其他函數中return只能導致函數執行結束
調用exit函數(在終止進程之前,會先調用atexit註冊的函數,調用_Exit終止進程,標C)
調用_exit(會立即終止 UC)或_Exit(標C,調用_exit終止進程)
atexit()用於註冊進程在退出時調用的函數
#include<stdio.h>
#include<stdlib.h>
void fa(){
printf("開始退出進程....\n");
exit(0);
}
void at(){
printf("這句話在進程結束之前調用\n");
}
int main(){
atexit(at);
fa();
printf("這句話打印不出來\n");
}
八,wait()----等待子進程結束
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>
#include<stdlib.h>
int main(){
pid_t pid = fork();
if(pid == 0){
printf("子進程開始運行,即將進入睡眠\n");
sleep(3);
printf("子進程運行結束\n");
exit(0);
}
//父進程
printf("父進程運行,運行的子進程是%d\n",pid);
printf("父進程等待子進程結束....\n");
//進入阻塞狀態,等待子進程結束
// pid_t res = wait(0);
//printf("等到結束的子進程是%d\n",res);
int result ;
pid_t res = wait(&result);
printf("等到結束的子進程是%d\n",res);
printf("result=%d\n",result);
if(WIFEXITED(result)){
printf("子進程是正常結束的\n");
//取返回值
printf("子進程返回值:%d\n",WEXITSTATUS(result));
}
return 0;
}
九,waitpid------等待某個指定的子進程
waitpid.c
#include<stdio.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<unistd.h>
int main(){
int pid1,pid2;
pid1 = fork();
if(pid1>0){
pid2 = fork();
}
if(pid1 == 0){//子進程一
printf("子進程一開始執行,睡眠3秒,pid=%d\n",getpid());
sleep(3);
printf("子進程一結束\n");
exit(100);
}
if(pid2 == 0){
printf("子進程二開始,pid=%d,睡1秒\n",getpid());
sleep(1);
printf("子進程二結束\n");
exit(200);
}
//父進程
printf("父進程等待子進程一結束\n");
int result;
waitpid(pid1,&result,0);
if(WIFEXITED(result)){
printf("子進程一的返回值:%d\n",WEXITSTATUS(result));
}
printf("父進程結束\n");
return 0;
}
十,exec函數
在程序中調用另外一個程序
exec函數一旦執行,後面的代碼都不會被執行了,因爲全部被覆蓋掉了
十一,system函數
相當於fork一個進程執行