进程常用指令 (从创建到回收 包含守护)
??????????????????????????????????????????????????????????????????????????????? 進(jìn)程
?
????????????????????????? 常用命令及基本介紹
?
ps -ef 查看所有進(jìn)程信息 (一般需要配合管道使用)
ps aux 查看進(jìn)程信息 且顯示進(jìn)程狀態(tài)
狀態(tài):
R 運(yùn)行態(tài) 正在運(yùn)行或可運(yùn)行
D 等待態(tài) 不可中斷
S 等待態(tài) 可中斷
T 停止態(tài)
Z 僵尸態(tài)
可追加:
+ 前臺(tái)運(yùn)行
< 高優(yōu)先級(jí)進(jìn)程
N 低優(yōu)先級(jí)進(jìn)程
top 動(dòng)態(tài)的查看進(jìn)程的信息及狀態(tài) 每隔3秒刷新一下 且能根據(jù)CPU的占用情況從大到小排序
?
/proc 目錄中存放著一些進(jìn)程相關(guān)文件
status 文件中存放進(jìn)程信息
fd 目錄中 存放進(jìn)程打開的所有文件的信息
?
nice -n number +./執(zhí)行文件名 作用是修改進(jìn)程的優(yōu)先級(jí) (number 為設(shè)定優(yōu)先級(jí)的大小 范圍為-20 ~ 19 19最低)
?
renice -n number +進(jìn)程號(hào) 作用是一般用于修改已有進(jìn)程的優(yōu)先級(jí) (number的作用同上)
?
普通用戶只能降低優(yōu)先級(jí) 不能拉高優(yōu)先級(jí)
ROOT用戶 可以降低優(yōu)先級(jí)也可以拉高優(yōu)先級(jí)
jobs 顯示當(dāng)前所有后臺(tái)進(jìn)程及信息 并對(duì)其編號(hào)排序
?
fg +排序號(hào)(jobs的排序號(hào)) 把相應(yīng)的后臺(tái)進(jìn)程轉(zhuǎn)成前臺(tái)進(jìn)程
?
Ctrl +z 讓前臺(tái)運(yùn)行進(jìn)程轉(zhuǎn)成掛起進(jìn)程(停止態(tài))
bg +排序號(hào) 讓掛起進(jìn)程轉(zhuǎn)成后臺(tái)運(yùn)行進(jìn)程
?
??????????????????????????????????????????????? 創(chuàng)建進(jìn)程
?
?
創(chuàng)建進(jìn)程函數(shù)
#include<unistd.h>
pid_t fork(void);
失敗返回-1
如果成功 父進(jìn)程返回子進(jìn)程的進(jìn)程號(hào) 子進(jìn)程返回0
?
int getpid(void) 返回進(jìn)程號(hào)
?
子進(jìn)程繼承了父進(jìn)程幾乎所有內(nèi)容 但不是全部
父子進(jìn)程都有自己獨(dú)立的空間
?
若父進(jìn)程先結(jié)束
子進(jìn)程成為孤兒進(jìn)程 被init進(jìn)程收養(yǎng) (也就是說它的父進(jìn)程變?yōu)閕nit進(jìn)程)
子進(jìn)程變成后臺(tái)進(jìn)程
?
若子進(jìn)程先結(jié)束
父進(jìn)程如果沒有及時(shí)回收 子進(jìn)程會(huì)變成僵尸進(jìn)程
?
子進(jìn)程是在fork()函數(shù)之后的下一條語句開始執(zhí)行
子進(jìn)程被創(chuàng)建后 父子進(jìn)程誰先執(zhí)行? 系統(tǒng)先調(diào)用誰 誰就先執(zhí)行 (如果沒有發(fā)生進(jìn)程調(diào)度 則父子進(jìn)程都有可能先執(zhí)行)
父進(jìn)程能否多次調(diào)用fork()函數(shù)? 可以 理論上不受影響
子進(jìn)程能否多次調(diào)用fork()函數(shù)? 可以 理論上不受影響
?
結(jié)束進(jìn)程
#include<stdlib.h>
#include<unistd.h>
void exit(int status)
void _exit(int status)
都會(huì)結(jié)束當(dāng)前進(jìn)程 并返回status
exit()結(jié)束進(jìn)程時(shí) 會(huì)刷新緩沖區(qū)(流)
?
?
????????????????????????????????????????????????? exec函數(shù)族
?
進(jìn)程調(diào)用exec函數(shù)族執(zhí)行某個(gè)程序
進(jìn)程當(dāng)前程序被執(zhí)行程序替換
讓父子進(jìn)程執(zhí)行不同的程序
父進(jìn)程創(chuàng)建子進(jìn)程
子進(jìn)程調(diào)用exec函數(shù)族·
父進(jìn)程不受影響
?
#include<unistd.h>
int execl(const char *path, const char *arg, ...)
int execlp(const char *file, const char *arg,...)
?
成功則執(zhí)行指定程序 失敗則返回EOF
path 執(zhí)行的程序的名稱 包含路徑
arg.... 傳遞給程序的參數(shù)
file 執(zhí)行的程序的名稱 不含路徑 需要在PATH環(huán)境變量中查找
?
#include<unistd.h>
int execv(const char *path, char *const argv[],...)
int execvp(const char *file, char *const srgv[],....)
成功執(zhí)行指定程序 失敗返回EOF
arg....封裝成指針數(shù)組的形式
?
Ps:char *arg[]= {"ls","-a", "-l", "/etc", NULL};
if(execv("/bin/ls", arg) < 0)
{
perror("execv");
}
?
#include <stdlib.h>
int system(const char *command)
成功返回command命令的返回值 失敗返回EOF
函數(shù)的實(shí)現(xiàn)過程 是 先創(chuàng)建一個(gè)子進(jìn)程 然后system()在子進(jìn)程中執(zhí)行命令 父進(jìn)程需要等待子進(jìn)程執(zhí)行完之后才能繼續(xù)執(zhí)行
?
???????????????????????????????????? 進(jìn)程回收
?
子進(jìn)程結(jié)束時(shí) 由父進(jìn)程回收
孤兒進(jìn)程 由init進(jìn)程回收
如果沒有及時(shí)回收 那么就會(huì)變成僵尸進(jìn)程 直到其父進(jìn)程執(zhí)行結(jié)束 僵尸進(jìn)程才會(huì)被init進(jìn)程回收
?
進(jìn)程回收函數(shù)
#include<unistd.h>
pid_t wait(int *status)
成功返回被回收的子進(jìn)程的進(jìn)程號(hào) 失敗返回EOF
如果子進(jìn)程沒有結(jié)束 父進(jìn)程會(huì)一直處于阻塞狀態(tài)
若有多個(gè)子進(jìn)程 哪個(gè)先結(jié)束 哪個(gè)先被回收
status用于保存子進(jìn)程返回值和結(jié)束方式的地址
status 如果為NULL 表示直接釋放子進(jìn)程的pcb 不接收返回值
?
子進(jìn)程正常結(jié)束的三種方式 exit / _exit / return 這三種都會(huì)返回一個(gè)值(0-255)
父進(jìn)程調(diào)用wait(status)進(jìn)行回收
WIFEEXITED(status) 可通過這個(gè)宏定義判斷這個(gè)子進(jìn)程是否是正常結(jié)束
WEXITSTATUS(status) 獲取子進(jìn)程返回值
WIFSIGNALED(status) 判斷子進(jìn)程是否是被信號(hào)結(jié)束
WTERMSIG(status) 獲取結(jié)束子進(jìn)程的信號(hào)類型
?
status這個(gè)變量中 第0位到第6位存放子進(jìn)程結(jié)束類型 如果為0 說明正常結(jié)束 非零說明被信號(hào)結(jié)束
第8位到第15位存放子進(jìn)程結(jié)束的返回值
?
?進(jìn)程回收函數(shù)
#include <unistd.h>
pid_t waitpid(pid_t pid, int *status, int option)
參數(shù)pid 是指定回收的對(duì)象 (如果不想指定 值設(shè)為-1即可)
參數(shù)option 是指定回收的方式 0或WNOHANG
option為0 如果子進(jìn)程尚未結(jié)束 父進(jìn)程則一直處于阻塞狀態(tài) 等待其結(jié)束 并將其回收
option為WNOHANG 如果子進(jìn)程尚未結(jié)束 父進(jìn)程不會(huì)一直阻塞 waitpid會(huì)返回0 代表子程序沒結(jié)束
如果子程序結(jié)束了 waitpid會(huì)返回進(jìn)程號(hào) 代表回收成功
成功則返回子進(jìn)程的進(jìn)程號(hào)或0 失敗返回EOF
如果返回進(jìn)程號(hào) 說明回收成功
如果返回0 說明子進(jìn)程還沒結(jié)束 并不代表回收失敗
如果返回EOF 說明沒有子進(jìn)程
?
??????????????????????????????????????????????? 守護(hù)進(jìn)程
?
守護(hù)進(jìn)程通常在系統(tǒng)啟動(dòng)時(shí)運(yùn)行 系統(tǒng)關(guān)閉時(shí) 結(jié)束
在linux系統(tǒng)中大量使用 很多服務(wù)程序以守護(hù)進(jìn)程形式運(yùn)行
?
特點(diǎn):
始終在后臺(tái)運(yùn)行
獨(dú)立于任何終端
周期性的執(zhí)行某種任務(wù)或等待處理特定事件
?
linux以會(huì)話和進(jìn)程組的方式管理進(jìn)程
每一個(gè)進(jìn)程都屬于一個(gè)進(jìn)程組
會(huì)話是一個(gè)或多個(gè)進(jìn)程組的集合 通常用戶打開一個(gè)終端時(shí) 系統(tǒng)會(huì)創(chuàng)建一個(gè)會(huì)話 所有通過該終端運(yùn)行的進(jìn)程都屬于這個(gè)會(huì)話
一個(gè)會(huì)話最多只能打開一個(gè)終端(也可以不打開)
當(dāng)某個(gè)終端結(jié)束時(shí) 所有相關(guān)的進(jìn)程都會(huì)被結(jié)束
?
?
????????? 守護(hù)進(jìn)程的創(chuàng)建
?
1. 創(chuàng)建子進(jìn)程 父進(jìn)程退出
此時(shí)該子進(jìn)程會(huì)成為孤兒進(jìn)程被init進(jìn)程收養(yǎng) 且在后臺(tái)運(yùn)行
并且該子進(jìn)程依然依附于終端 一旦終端關(guān)閉子進(jìn)程會(huì)被結(jié)束
(此時(shí)進(jìn)程還不屬于守護(hù)進(jìn)程)
?
2. 在子進(jìn)程中 創(chuàng)建新會(huì)話
實(shí)現(xiàn)函數(shù) setsid()
該子進(jìn)程成為會(huì)話組組長
且不再依賴于原先終端
?
3. 更改當(dāng)前工作目錄
可更改為
chdir("/")(這是根目錄 普通用戶的權(quán)限是只讀 可執(zhí)行 不可寫)
或 chdir("/tmp")(所有的用戶在該目錄下都是可讀可寫可執(zhí)行)
更改目錄的原因:守護(hù)進(jìn)程一直在后臺(tái)運(yùn)行 其工作目錄是不可被卸載的 所以創(chuàng)建守護(hù)進(jìn)程時(shí) 需 要把子進(jìn)程的工作目錄更改到一個(gè)永遠(yuǎn)不會(huì)被修改的目錄中
?
4.重設(shè)文件權(quán)限掩碼
實(shí)現(xiàn)函數(shù) umask(number) number為設(shè)定的掩碼 一般為0 代表不會(huì)屏蔽任何權(quán)限位
重新設(shè)定的掩碼只會(huì)對(duì)當(dāng)前進(jìn)程有效 不會(huì)影響其他進(jìn)程
5 關(guān)閉打開的文件描述符
因?yàn)樽舆M(jìn)程會(huì)繼承父進(jìn)程的一些文件 所以在這里需要把這些文件關(guān)閉掉
實(shí)現(xiàn)函數(shù) getdtablesize() 作用獲取文件個(gè)數(shù)
int i;
for(i=0; i<getdablesize();i++)
close(i);
已脫離終端 stdin /stdout / stderr 無法使用
?
Like:
創(chuàng)建守護(hù)進(jìn)程 每隔1秒 將系統(tǒng)時(shí)間寫入到time.log文件中
?
code:
int main()
{
pid_t pid;
FILE *fp;
time_t t;
int i;
?
if((pid = fork() < 0)
{
perror("fork");
exit(-1);
}
else if(pid > 0)
exit(0);
?
setpid();//創(chuàng)建新會(huì)話
umask(0); //重設(shè)文件掩碼
chdir("/tmp"); // 更改文件目錄
?
for(i =0 ;i < getdablesize(); i++) //關(guān)閉繼承的父進(jìn)程的文件
close(i);
?
if((fp = fopen("time.log", "a")) == NULL)
{
perror("fopen");
exit(-1);
}
?
while(1)
{
time(&t);
fprintf(fp, "%s", ctime(&t));
fflush(fp);
sleep(1);
}
}
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的进程常用指令 (从创建到回收 包含守护)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux中标准I/O 文件I/O 及库
- 下一篇: 二级C选择知识点(部分)