-
进程的概念
程序
> 存放在磁盘上的指令和数据的有序集合(文件); > 静态的;复制代码
进程
> 执行一个程序所分配的资源的总称; > 进程是程序的一次执行过程; > 动态的,包括创建、调度、执行和消亡;复制代码
-
进程的内容
代码、 用户数据段、 系统数据段
系统数据段包括了进程控制块、CPU寄存器的值、堆栈;
进程控制块(pcb)
> 进程标识PID; > 进程用户的信息; > 进程状态、优先级; > 文件描述符表(记录了系统中打开的所有的文件的信息);复制代码
CPU寄存器
program counter (存放的是下一条指令的地址);
栈
保存了所有的局部变量;
-
进程的类型
交互进程
在shell下启动。可以在前台运行,也可以是在后台运行;
批处理进程
和在终端无关,被提交到一个作业队列中,被作业管理工具顺序执行(开发时较少使用);
守护进程
和终端无关,一直在后台运行(生命期很长);
-
进程状态
运行态
程序正在运行,或者准备运行;
等待态
程序在等待一个事件的发生或者某种系统资源(可中断和不可中断);
停止态
进程被终止,收到信号后可继续运行;
死亡态
已终止的进程,但pcb没有被释放;
-
一些相关命令
ps -ef
显示当前时刻系统中所有进程的信息;ps -ef|grep <>
筛选显示ps aux|grep <>
比-ef
多显示进程的当前状态;top
查看进程的动态信息;/proc
进入该目录下查看进程的详细信息;nice -n <NI> ./<001>
按用户指定的优先级运行进程(默认的 nice 值是 0 ,区间为 -20 到 19),nice值越小,优先级越高;renice -n <NI> <PID>
改变正在运行进程的优先级;jobs
查看一个后台进程;fg <PID>
把一个后台进程放到前台;bg <PID>
让处于停止态的后台进程运行起来; -
创建子进程
-
fork函数
头文件:
#include <unistd.h>
函数原型:
pid_t fork(void);
返回值:
创建新的进程,失败时返回-1;
fork()
被调用一次会返回两次,成功时父进程返回子进程的进程号,子进程返回 0 ;通过
fork
的返回值区分父进程和子进程;示例:
#include#include #include #include int main(int argc,const char *argv[]){ pid_t pid; if ((pid = fork()) < 0) { perror("fork"); return -1; } else if (pid == 0) { printf("child process: my pid is %d\n",getpid()); } else{ printf("parent process: my pid is %d\n",getpid()); } return 0;}复制代码
-
父子进程
子进程继承了父进程的内容;
父子进程有独立的地址空间,互不影响;
若父进程先结束,子进程成为孤儿进程,会被
init
进程收养,同时变为后台进程;若子进程先结束,父进程没有及时回收,子进程则变为僵尸进程(pcb未被释放);
父子进程的运行顺序不确定,取决于内核的调度;
-
结束进程
-
exit / _exit函数
头文件:
#include <stdlib.h>
#include <unistd.h>
函数原型:
void exit(int status);
void _exit(int status);
返回值;
结束当前进程并将status返回;
exit 结束进程时会刷新流的缓冲区;
示例:
#include
/*exit()的头文件*/#include /*_exit()的头文件*/#include int main(int argc,const char *argv[]){ printf("success"); /*换成_exit(0)则屏幕无输出*/ exit(0); printf("success too"); return 0;}复制代码 -
exec函数族
进程的当前内容被替换,实现父子进程执行不同的程序;
-
execl / execlp 函数
头文件:
#include <unistd.h>
函数原型:
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arc, ...);
path ,执行程序的名称和路径(绝对路径或相对路径);
arg... 传递给执行程序的参数列表;
file 执行的程序的名称,在PATH(shell的环境变量)中查找;
返回值:
成功执行指定的程序,失败则返回EOF;
示例:(执行ls命令,显示/etc目录下所有的文件详细信息)
if(execl("/bin/ls","ls","-a","-l","/etc",NULL) < 0) { perror("exec error");}复制代码
if(execlp("ls","-a","-l","/etc",NULL) < 0) { perror("execlp error");}复制代码
-
execv / execvp 函数
头文件:
#include <unistd.h>
函数原型:
int execv(const char *path, char *const argv[]);
int sescvp(const char *file, char *const argv[]);
相较于
execl()和execlp()
,参数列表封装成字符指针数组;返回值:
成功执行指定的程序,失败则返回EOF;
示例:(功能同上)
/*定义一个字符指针数组*/char *const buf[] = { "ls","-a","-l","/etc",NULL};if(execv("/bin/ls",buf) < 0) { perror("execv");}复制代码
-
system 函数
属于比较简单的方法,不手动创建子进程;
头文件:
#incude <stdlib.h>
函数原型:
int system(const char *command);
在当前进程中会自己创建子进程;
返回值:
成功时返回命令 command 的返回值,失败时返回EOF;
当前进程等待 command 执行结束之后才继续执行;
-
进程回收
-
wait 函数
-
waitpid 函数