一.进程概念
程序:
存放在磁盘上的指令和数据的有序集合(文件)
静态的
进程:
执行一个程序所分配的资源的总称
动态的
进程包含的内容:
BSS段:存放程序中未初始化的全局变量
数据段:已初始化的全局变量
代码段:程序执行代码
堆(heap):malloc等函数分配内存
栈(stack):局部变量,函数参数,函数的返回值
进程控制块(pcb):PID, 进程用户、(进程状态、优先级),文件描述符表
进程类型:
交互进程:在shell下启动,可以在前台运行,也可以在后台运行(&)。
批处理进程:和终端无关,被提交到一个队列中以便顺序运行。
守护进程:和终端无关,一直在后台运行。
进程状态:
二.进程的命令
查看进程信息:
ps 查看系统进程快照
top 动态查看进程。
/proc 查看进程详细信息
改变进程优先级
nice [-n NI值] 命令
NI 范围是 -20~19。数值越大优先级越低
普通用户调整 NI 值的范围是 0~19,而且只能调整自己的进程。
普通用户只能调高 NI 值,而不能降低。如原本 NI 值为 0,则只能调整为大于 0。
./test & 把test程序后台运行
jobs 查看后台进程
bg 将挂起的进程在后台运行
fg 把后台运行的进程放到前台运行
三.创建子进程
#include <unistd.h>
pid_t fork(void);
创建新的进程,失败时返回-1
成功时父进程返回子进程的进程号,子进程返回0
通过fork的返回值区分父进程和子进程
注意:
子进程只执行fork之后的代码
父子进程执行顺序是操作系统决定的。
子进程继承了父进程的内容
父子进程有独立的地址空间,互不影响
若父进程先结束
子进程成为孤儿进程,被init进程收养
子进程变成后台进程
若子进程先结束
父进程如果没有及时回收,子进程变成僵尸进程
四.进程的退出
#include <stdlib.h>
#include <unistd.h>
void exit(int status);
void _exit(int status);
main函数结束时会隐式地调用exit函数,普通函数return是返回上一级。
五.进程的回收
#include <unistd.h>
pid_t wait(int *status);
成功时返回回收的子进程的进程号;失败时返回EOF
若子进程没有结束,父进程一直阻塞
#include <unistd.h>
pid_t waitpid(pid_t pid, int *status, int option);
wait(wait_stat) 等价于waitpid(-1,wait_stat,0)
六.举例
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char** argv){
pid_t pid;
pid_t rpid;
pid = fork();
int status;
if(pid<0){
perror("fork");
return 0;
}
else if(pid == 0){
sleep(10);
printf("child will exit\n");
exit(2);
}else if(pid >0){
//rpid = wait(&status);
sleep(20);
waitpid(-1,&status,WNOHANG);
printf("Get child status=%x\n",WEXITSTATUS(status));
}
while(1){
sleep(1);
}
}