進程
* 進程 程序的一次動態執行過程
進程生命周期:
- 創建:創建虛擬地址空間、地址空間分段,創建task_struct結構(PCB進程控制塊)
- 調度:內核管理task_struct結構組成的鏈表,根據優先級和進程屬性分配時間片
- 執行:進程獲得時間片到cpu中執行
- 消亡:進程結束,回收虛擬地址空間,由父進程回收task_struct結構。
虛擬地址空間分段:
- stack:棧區,存放局部變量、函數傳參、返回地址
- 不要進行太深的遞歸防止棧溢出。
- heap:堆區,用來給malloc使用的空間
- 使用完成記得free防止內存泄露
- .bss:未初始化的全局變量/靜態變量static(作用域)
- .data:已初始化的全局/靜態變量
- .text:代碼、常量
* task_struct:pid進程號 ppid父進程號 用到的資源 內存映射表 打開的文件
程序和進程有什么區別 ?
- 程序是靜態的,是一個文件
- 進程是動態的一個執行過程,包括創建、調度、執行、消亡整個生命周期。
* ps 查看當前終端的進程 任意的命令也是一個進程
- ps -ef 查看更多進程信息,可以查看到父進程ID,tty為?表示與終端無關。
- ps -aux可以查看進程狀態
- ps -axj可以查看到會話組
- top可以動態查看進程狀態包括優先級 空格刷新 q退出
* pstree 樹形查看進程關系,init是所有進程的根,進程號為1
* 進程組:為了統一管理一些進程分的組
* 會話組:比進程組更大的單位,可以包含多個進程組
進程分類:
交互進程:前臺進程(既可以輸入、也可以輸出)、后臺(只能輸出)
-
后臺進程產生:./a.out &
- ctrl+z 暫停,bg 放到后臺
- fg 可以喚到前臺
批處理進程
守護進程
-
進程狀態:
S:睡眠/等待態
T:停止態(暫停)
R:運行態
Z:僵尸態,父進程沒有回收子進程資源
+表示前臺 s會話組長 l多線程 <優先級比較高 N表示優先級比較低
* kill 給進程發送信號 -l可以查看所有的信號 -9強制結束一個進程
* 運行前指定優先級 nice ./a.out 10
* 運行時改變優先級 renice 5 pid
* 父進程退出,子進程會成為孤兒進程,孤兒進程由init接管
* fork();創建一個子進程,在父進程中返回子進程的pid,在子進程中返回0。
* fork之前的內容拿到結果(繼承),之后的內容原樣復制。
* fork之前打開的文件,復制時會延續之前的結構,會使用同一個文件指針,父子進程操作文件會互相造成影響。
* getpid獲得自己的pid
* getppid獲得父進程的pid
execl :
- execl(可執行文件,執行方式,其他參數,以NULL結尾);
- 替換當前地址空間內容,執行新的可執行文件。
- ...可變長度傳參,以NULL結尾。
_exit :
- _exit(int status);
- 不清理緩沖區,立即退出當前進程。status返回給父進程,父進程通過wait一族函數回收。
* exit() ; 退出進程時清理緩沖區。
* wait() ; 阻塞等待子進程改變狀態,子進程改變狀態之后wait變成非阻塞。
waitpid(pid,status,options);
- pid: <-1:等待組ID為-pid的子進程
- -1:等待任意子進程
- 0:等待當前進程組的子進程
- >0:等待指定的子進程
- options:
- 0:阻塞等待
- WNOHANG非阻塞,并且沒有子進程退出,直接返回0
練習 :
通過fork創建一個子進程,父進程復制1.txt的前一半,子進程復制1.txt的后一半,然后寫入到2.txt。
/************************************************************************
> File Name: homework.c
> Author: Lin
> Mail: linbb@farsight.cn
> Created Time: 2016年12月01日 星期四 09時11分48秒
*******************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define SIZE 64
int main(int argc, const char *argv[])
{
pid_t p;
char buf[SIZE];
int fp1,fp2;
long len,sum = 0,n;
fp1 = open("1.txt",O_RDONLY|O_EXCL);
if(-1 == fp1)
{
perror("open1");
return -1;
}
fp2 = open("2.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);
if(-1 == fp2)
{
perror("open2");
return -1;
}
len = lseek(fp1,0,SEEK_END);
if(-1 == len)
{
perror("lseek 1");
return -1;
}
len /= 2;
p = fork();
if(-1 == p)
{
perror("fork");
return -1;
}
if(p == 0)
{
if(-1 == lseek(fp1,len,SEEK_SET))
{
perror("lseek 2");
return -1;
}
if(-1 == lseek(fp2,len,SEEK_SET))
{
perror("lseek 3");
return -1;
}
while(1)
{
n = read(fp1,buf,SIZE);
// printf("child:n = %ld\n",n);
if(-1 == n)
{
perror("read");
return -1;
}
if(0 == n)
break;
write(fp2,buf,n);
}
}else
{
if(-1 == close(fp1))
{
perror("close 1");
return -1;
}
if(-1 == close(fp2))
{
perror("close 2");
return -1;
}
fp1 = open("1.txt",O_RDONLY|O_EXCL);
if(-1 == fp1)
{
perror("open1");
return -1;
}
fp2 = open("2.txt",O_WRONLY);
if(-1 == fp2)
{
perror("open2");
return -1;
}
if(-1 == lseek(fp1,0,SEEK_SET))
{
perror("lseek 4");
return -1;
}
if(-1 == lseek(fp2,0,SEEK_SET))
{
perror("lseek 5");
return -1;
}
while(1)
{
n = read(fp1,buf,SIZE);
sum += n;
// printf("father:n = %ld,sum = %ld,len = %ld\n",n,sum,len);
if(-1 == n)
{
perror("read");
return -1;
}
if(sum > len)
{
write(fp2,buf,n - (sum - len));
break;
}
write(fp2,buf,n);
}
}
if(-1 == close(fp1))
{
perror("close 1");
return -1;
}
if(-1 == close(fp2))
{
perror("close 2");
return -1;
}
return 0;
}