学习视频 <— 众所周知B站是中国最大的学习网站 2333
● 程序
➢存放在磁盘上的指令和数据的有序集合(文件)
➢静态的
● 进程
➢执行一个程序所分配的资源的总称
➢进程是程序的一次执行过程
➢动态的,包括创建、调度、执行和消亡
在系统数据段中包含以下部分:进程控制块、CPU寄存器值、堆栈
● 进程控制块(pcb)
➢进程标识PID
➢进程用户
➢进程状态、优先级
➢文件描述符表
● 交互进程:在shell下启动。 以在前台运行,也可以在后台运行
● 批处理进程:和在终端无关,被提交到一个作业队列中以便顺序执行
● 守护进程:和终端无关,一直在后台运行
● 运行态:进程正在运行,或者准备运行
● 等待态:进程在等待一个事件的发生或某种系统资源
➢可中断
➢不可中断
● 停止态:进程被中止,收到信号后可继续运行
● 死亡态:已终止的进程,但pcb没有被释放
● ps:查看系统进程快照
ps -ef #列出所有进程
ps -ef|grep xxx #显示xxx程序的进程
ps aux|grep xxx #显示xxx程序的进程 (增加了状态显示)
man ps #显示ps命令的相关内容
top #每隔3秒刷新进程状态,同时会实时统计进程,按资源占用率排列
按键q或者ctrl+z退出top命令
● /proc:查看进程详细信息
cd /proc #打开proc文件夹
ls #会显示很多数字名文件夹
● nice:按用户指定的优先级运行进程
● renice:改变正在运行进程的优先级
renice -n 优先级 进程PID #修改进程优先级
● jobs:查看后台进程
● bg:将挂起的进程在后台运行
● fg:把后台运行的进程放到前台运行
● 父进程与子进程的概念
一个进程,包括代码、数据和分配给进程的资源。fork()函数通过系统调用创建一个与原进程(父进程)几乎完全相同的进程(子进程),也就是说两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。一个进程调用fork()函数后,系统先给子进程分配资源,例如存储数据和代码的空间,然后把父进程的所有值都复制到子进程中,相当于克隆了一个自己,只有少数值与父进程的值不同,比如PID和PPID父子进程不同。
父进程与子进程的运行(重要)
子进程继承了父进程的内容
父子进程有独立的地址空间,互不影响
若父进程先结束
➢子进程成为孤儿进程,被init进程收养
➢子进程变成后台进程
若子进程先结束
➢父进程如果没有及时回收,子进程变成僵尸进程
子进程从何处开始运行?
➢子进程被fork函数创建出来后,从fork的下一条语句开始执行
父子进程谁先执行?
➢不确定,由于内核来调度
父进程能否多次调用fork? 子进程呢?
➢都是可以的,编程时要注意回收子进程
#include
pid_t pid=fork();
➢创建新的进程,失败时返回-1.
➢成功时父进程返回子进程的进程号,子进程返回0
➢通过fork的返回值区分父进程和子进程
● 说明
两种方法都可以结束当前的进程并将status返回,当使用exit结束进程时会刷新(流)缓冲区,即内容仍会被写入文件中;而_exit结束进程时,如果缓冲区里的内容还没有写入文件中,缓冲区信息丢失,则不会写入文件里。
#include
#include
void exit(int status);
void _exit(int status);
● 说明
函数族是指一组函数
进程可以通过调用exec函数族的函数执行别的程序
进程当前内容被指定的程序替换
实现让父子进程执行不同的程序
➢父进程创建子进程
➢子进程调用exec函数族
➢父进程不受影响
● execl函数 / execlp函数
● execv函数 / execvp函数
● system函数
➢比前几种方法简单易用
➢成功时返回命令command的返回值;失败时返回EOF
➢当前进程等待command执行结束后才继续执行
#include
int system(const char *command);
● 说明
➢子进程结束时由父进程回收
➢孤儿进程由init进程回收
➢若没有及时回收会出现僵尸进程
● wait函数
➢成功时返回回收的子进程的进程号;失败时返回EOF
➢若子进程没有结束,父进程一直阻塞
➢若有多个子进程,哪个先结束就先回收
➢要回收几个子进程就需要调用几次wait函数
➢status指定保存子进程返回值和结束方式的地址
➢status为NULL表示直接释放子进程PCB,不接收返回值
#include
pid_t wait(int *status);
int status; //用来接收返回值和结束方式
pid_t pid;
if (pid = fork())<0) //判断进程创建是否成功
{
perror("fork"); exit(-1);
}
else if (pid == 0) //是否是子进程
{
sleep(1); //睡眠1秒
exit(2);
}
else //主进程
{
wait(&status); printf("%x\n", status);
}
子进程通过exit/_ _exit / return 返回某个值(0-255)
父进程调用wait(&status)回收
➢WIFEXITED(status) 判断子进程是否正常结束
➢WEXITSTATUS(status) 获取子进程返回值
➢WIFSIGNALED(status) 判断子进程是否被信号结束
➢WTERMSIG(status) 获取结束子进程的信号类型
● waitpid函数
➢成功时返回回收的子进程的pid或0;失败时返回EOF
➢pid可用于指定回收哪个子进程或任意子进程
➢status指定用于保存子进程返回值和结束方式的地址
➢option指定回收方式,0(阻塞)或WNOHANG(非阻塞)
#include
pid_t waitpid(pid_t pid,int *status,int option);
waitpid(pid, &status, 0);
waitpid(pid, &status, WNOHANG);
waitpid(-1, &status, 0);
waitpid(-1, &status, WNOHANG);
● 概念
➢守护进程(Daemon)是Linux三种进程类型之一
➢通常在系统启动时运行,系统关闭时结束
➢Linux系统中大量使用,很多服务程序以守护进程形式运行
● 特点
➢始终在后台运行
➢独立于任何终端
➢周期性的执行某种任务或等待处理特定事件
● 会话、控制终端
➢Linux以会话(session)、进程组的方式管理进程
➢每个进程属于一个进程组
➢会话是一个或多个进程组的集合。通常用户打开一个终端时,
系统会创建一个会话。所有通过该终端运行的进程都属于这个会话
● 创建守护进程
(待续)
(待续)