uc_day06

一,進程
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一個進程執行

















發佈了51 篇原創文章 · 獲贊 2 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章