Linux-c系統編程

進程相關的概念

程序和進程

程序:二進制文件、佔用磁盤空間linux

進程:運行着的程序,數據在內存中,佔用系統資源,CPU,物理內存()shell

PCB描述進程(進程控制塊)

把描述進程的全部信息的那條記錄叫作 PCB(process control block)數據結構

每一個進程有且僅有一個PCB併發

linux下的PCB:task_struct函數

存放在/usr/src/kernels/2.6.32-431.el6.i686/include/linux/sched.hui

 

程序計數器:程序中即將被執行的下一條指令的地址。spa

內存指針:包括程序代碼和進程相關數據的指針,還有和其餘進程共享的內存塊指針設計

進程優先級

優先級:相對於其餘進程的優先級。指針

ps -al #可查看進程優先級
renice -5 -p PID #修改進程優先級
#top命令能夠實時動態地查看系統的總體運行狀況

進程的五種狀態

  1. R 運行 (正在運行或在運行隊列中等待) code

  2. S 中斷 (休眠中, 受阻, 在等待某個條件的造成或接受到信號)

  3. D 不可中斷 (收到信號不喚醒和不可運行, 進程必須等待直到有中斷髮生)

  4. Z 僵死 (進程已終止, 但進程描述符存在, 直到父進程調用wait4()系統調用後釋放)

  5. T 中止 (進程收到SIGSTOP, SIGSTP, SIGTIN, SIGTOU信號後中止運行運行)

並行和併發

並行:指兩個或者多個事件在同一時刻發生;

併發:指兩個或多個事件在同一時間間隔發生

孤進程和僵進程

孤兒進程:父進程先退出,子進程就稱之爲「孤兒進程」

殭屍進程:當進程退出而且父進程(使用wait()系統調用)沒有讀取到子進程退出的返回代碼時就會產生僵進程。

殭屍進程放棄了幾乎全部的內存空間,沒有任何可執行代碼,也不能別調度,

僅僅在進程列表保留位置,並且不佔用任何內存空間

ps/kill命令的使用

ps -aux  #列出進程詳細信息,可配合grep篩選

kill 1234 #殺死指定PID的進程

fork/getpid/getppid函數的使用

fork函數,計算機程序設計中的分叉函數

若成功調用一次則返回兩個值,子進程返回0,父進程返回子進程標記;不然,出錯返回-1

getpid返回當前進程標識,getppid返回父進程標識。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

int main(void)
{
pid_t pid=fork();
switch(pid)
{
case -1:
printf("Fork Error\n");
case 0:
printf("\nI'm Child My PID=%d\n",getpid());
printf("My Parent PID=%d\n",getppid()); //這個父進程的父進程
printf("Child is Exiting\n");
exit(0);
default:
printf("\nI'm Parent My PID=%d\n",getpid());
printf("My Child PID is %d\n",pid);
}
}

execl/execlp函數的使用

Fork炸彈

這條命令在Linux shell下運行會讓系統死機

具體意義百度百科上有

execl/execlp函數的使用

execl()函數:執行文件函數

表示後邊的參數以可變參數的形式給出且都以一個空指針結束

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
   printf("entering main process---\n");
   execl("/bin/ls","ls","-l",NULL);
   printf("exiting main process ----\n");
   return 0;
}

利用execl將當前進程main替換掉,最後那條打印語句不會輸出

execlp()函數:從PATH環境變量中查找文件並執行

第一個參數path不用輸入完整路徑,給出命令名便可,它會在環境變量PATH當中查找命令

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
   printf("entering main process---\n");
   execlp("ls","ls","-l",NULL);
   printf("exiting main process ----\n");
   return 0;
}

wait函數和waitpid函數的使用

wait()函數用於使父進程(也就是調用wait()的進程)阻塞,

直到一個子進程結束或者該進程接收到了一個指定的信號爲止。

若是該父進程沒有子進程或者它的子進程已經結束,則wait()函數就會當即返回。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
pid_t pid,pw;
pid=fork();
if(pid<0)
{
puts("fork eorro!\n");
exit(1);
}
else if(pid==0) //子進程
{
printf("I'm Child,pid=%d\n",getpid());
sleep(5);
exit(0);
}
else
{
pw=wait(NULL);
printf("I catch a Child,PID is %d\n",pw);
}
exit(0);
}

系統調用exit後,該進程並不是立刻消失,而是留下一個叫殭屍進程的數據結構

waitpid()的做用和wait()同樣,但它並不必定要等待第一個終止的子進程(它能夠指定須要等待終止的子進程)

它還有若干選項,如可提供一個非阻塞版本的 wait()功能,也能支持做業控制。

實際上,wait()函數只是 waitpid()函數的一個特例,在Linux 內部實現 wait()函數時直接調用的就是waitpid()函數

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
  pid_t pc,pr;
  pc=fork();
  if (pc<0)/* fork錯誤*/
  {
      printf("fork error\n");
      exit(1);
  }
  else if(pc==0)/*在子進程中*/
  {
      sleep(5);
      exit(0);
  }
  else
  {
      do {/* 使用了WNOHANG參數,waitpid不會在這裏等待 */
          pr=waitpid(pc,NULL,WNOHANG);
          if (pr==0)
          {
              printf("No child exit\n");
              sleep(1);
          }
        }while (pr==0);
      if (pr==pc)
          printf("successfully get child %d\n",pr);
      else
          printf("wait child error\n");
  }
  return 0;
}

 

相關文章
相關標籤/搜索